Low*_*wah 8 dd posix binary head
刚刚遇到这个问题,并从选择的答案中学到了很多东西:使用 dd 创建随机数据并获得“部分读取警告”。现在警告后的数据真的是随机的吗?
不幸的是,建议的解决方案head -c
不可移植。
对于坚持这dd
是答案的人,请仔细阅读链接的答案,其中详细解释了为什么dd
不能成为答案。另外,请注意这一点:
$ dd bs=1000000 count=10 if=/dev/random of=random
dd: warning: partial read (89 bytes); suggest iflag=fullblock
0+10 records in
0+10 records out
143 bytes (143 B) copied, 99.3918 s, 0.0 kB/s
$ ls -l random ; du -kP random
-rw-rw-r-- 1 me me 143 Apr 22 19:19 random
4 random
$ pwd
/tmp
Run Code Online (Sandbox Code Playgroud)
Gil*_*il' 12
不幸的是,操作二进制文件的内容dd
几乎是 POSIX 中唯一的工具。尽管文本处理工具(cat
, sed
, awk
, ...)的大多数现代实现都可以操作二进制文件,但这不是 POSIX 所要求的:一些较旧的实现确实会阻塞空字节、未以换行符终止的输入或环境字符中的无效字节序列编码。
dd
安全使用是可能的,但很困难。我花费大量精力引导人们远离它的原因是,有很多建议可以dd
在既无用又不安全的情况下进行推广。
问题dd
在于它的块概念:它假设调用read
返回一个块;如果read
返回较少的数据,你会得到一个部分块,它会抛出类似skip
和count
关闭的东西。这是一个说明问题的示例,其中dd
从传输数据相对较慢的管道读取:
yes hello | while read line; do echo $line; done | dd ibs=4 count=1000 | wc -c
Run Code Online (Sandbox Code Playgroud)
在 bog 标准的 Linux(Debian jessie,Linux 内核 3.16,dd
来自 GNU coreutils 8.23)上,我得到了高度可变的字节数,范围从大约 3000 到几乎 4000。将输入块大小更改为 6 的除数,然后输出始终为 4000 字节,正如人们天真地预期的那样——输入以dd
6 字节的突发形式到达,只要一个块不跨越多个突发,dd
就可以读取一个完整的块。
这提出了一个解决方案:使用输入块大小 1。无论输入如何产生,dd
如果输入块大小为 1,则无法读取部分块。(这并不完全显而易见:dd
如果它被信号中断,则可以读取大小为 0 的块 - 但如果它被中断通过信号,read
系统调用返回-1。read
只有在文件以非阻塞模式打开时才可能返回0,在这种情况下,read
最好根本不考虑执行a。在阻塞模式下,read
只有在文件末尾返回 0。)
dd ibs=1 count="$number_of_bytes"
Run Code Online (Sandbox Code Playgroud)
这种方法的问题在于它可能很慢(但并不慢得惊人:仅比head -c
我的快速基准测试慢 4 倍)。
POSIX 定义了其他读取二进制数据并将其转换为文本格式的工具:(uuencode
以历史 uuencode 格式或 Base64od
输出),(输出八进制或十六进制转储)。两者都不适合手头的任务。uuencode
可以撤消uudecode
,但计算输出中的字节数很尴尬,因为每行输出的字节数没有标准化。有可能从 获得明确定义的输出od
,但不幸的是没有 POSIX 工具可以反过来(它可以完成,但只能通过 sh 或 awk 中的慢循环,这违背了这里的目的)。
小智 5
较新版本的 GNU 实现dd
有一个count_bytes
iflag。例如:
cat /dev/zero | dd count=1234 iflag=count_bytes | wc -c
Run Code Online (Sandbox Code Playgroud)
将输出类似
2+1 records in
2+1 records out
1234 bytes (1.2 kB, 1.2 KiB) copied, 0.000161684 s, 7.6 MB/s
1234
Run Code Online (Sandbox Code Playgroud)