我创建了一个带有随机数据的 1TB 文件dd if=/dev/urandom of=file bs=1M count=1000000。现在我检查kill -SIGUSR1 <PID>进度并得到以下信息:
691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s
Run Code Online (Sandbox Code Playgroud)
我无法解释警告。它说什么?警告后我的文件真的是随机的还是有问题?什么+ 0或+1的800950+1 Datensätze ein和800950+0 Datensätze aus是什么意思?警告后为+1。它是一个错误计数吗?
Gil*_*il' 53
总结:dd是一个难以正确使用的胡思乱想的工具。不要使用它,尽管有很多教程告诉你。dd有一种“unix 街头信誉”的感觉——但如果你真的了解你在做什么,你就会知道你不应该用 10 英尺长的杆子去碰它。
ddread每个块对系统调用进行一次调用(由 的值定义bs)。不能保证read系统调用返回与指定缓冲区大小一样多的数据。这往往适用于常规文件和块设备,但不适用于管道和某些字符设备。请参阅dd 何时适合复制数据?(或者,何时是 read() 和 write() 部分)以获取更多信息。如果read系统调用返回少于一个完整块,则dd传输部分块。它仍然复制指定数量的块,因此传输的字节总数少于请求的字节数。
关于“部分读取”的警告准确地告诉您:其中一个读取是部分的,因此dd传输了一个不完整的块。在块计数中,+1表示一个块被部分读取;由于输出计数为+0,因此所有块都被写出为已读。
这不会影响数据的随机性:dd写出的所有字节都是它从中读取的字节/dev/urandom。但是您得到的字节数比预期的要少。
Linux 可以/dev/urandom容纳任意大的请求(来源:extract_entropy_userin drivers/char/random.c),因此dd读取它时通常是安全的。但是,读取大量数据需要时间。如果进程接收到信号,read系统调用会在填充其输出缓冲区之前返回。这是正常行为,应用程序应该read循环调用;dd不这样做,由于历史原因(它dd的起源是模糊的,但它似乎是作为访问磁带的工具开始的,它具有特殊的要求,并且从未适应成为通用工具)。当您检查进度时,这会向dd进程发送中断读取的信号。您可以选择知道多少字节dd将全部复制(确保不要中断它 - 没有进度检查,没有暂停),或者知道dd到目前为止复制了多少字节,在这种情况下,您无法知道它将复制多少字节。
ddGNU coreutils的版本(如在非嵌入式 Linux 和 Cygwin 上发现的)有一个标志fullblock,告诉在循环中dd调用read(和同上 for write),因此总是传输完整的块。错误信息提示您使用它;你应该总是使用它(在输入和输出标志中),除非在非常特殊的情况下(主要是在访问磁带时)——如果你使用dd了,那就是:通常有更好的解决方案(见下文)。
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
Run Code Online (Sandbox Code Playgroud)
确定dd会做什么的另一种可能方法是传递块大小为 1。然后您可以知道从块计数中复制了多少字节,但我不确定如果 aread在读取第一个之前被中断会发生什么字节(这在实践中不太可能发生,但可能发生)。然而,即使它有效,这也很慢。
关于使用的一般建议dd是不要使用dd。虽然dd经常被宣传为访问设备的低级命令,但实际上并非如此:所有的魔法都发生在设备文件 (the /dev/…) 部分,dd只是一个普通工具,很有可能被误用导致数据丢失. 在大多数情况下,有一种更简单、更安全的方式来做你想做的事,至少在 Linux 上是这样。
例如,要在文件开头读取一定数量的字节,只需调用head:
head -c 1000000m </dev/urandom >file
Run Code Online (Sandbox Code Playgroud)
我在我的机器上做了一个快速基准测试,并没有观察到dd大块大小和head.
如果您需要在开头跳过一些字节,请使用管道tail输入head:
dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output
Run Code Online (Sandbox Code Playgroud)
如果要查看进度,请调用lsof以查看文件偏移量。这仅适用于常规文件(示例中的输出文件),不适用于字符设备。
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
Run Code Online (Sandbox Code Playgroud)
您可以调用pv以获取进度报告(比 更好dd),但代价是管道中的额外项目(性能方面,几乎无法察觉)。
fro*_*utz 12
当dd在单次读取中无法获得足够的数据来填充块时,就会出现警告。这种情况发生在不稳定或缓慢的数据源,或者以比您请求的块大小更小的单位写入数据的源。
数据完整性没有问题,但问题是将dd部分读取仍然计为读取块。
如果您不使用该count选项,则警告几乎无关紧要,这只是性能方面的考虑。但是使用count,您将无法获得所需的数据量。由于部分读取,of会比count*bs末尾小。
因此,当您使用 时count,从技术上讲,您也应该始终使用iflag=fullblock。
的+x应该是部分块的数量。