简介:dd
是一个怪异的工具,很难正确使用。尽管有许多教程告诉您,但不要使用它。dd
它具有“ unix street cred”的氛围-但如果您真正了解自己在做什么,就会知道不应该用10英尺长的杆子碰它。
dd
read
每个块(由的值定义bs
)对系统调用进行一次调用。不能保证read
系统调用返回的数据与指定的缓冲区大小一样多。这通常适用于常规文件和块设备,但不适用于管道和某些字符设备。请参阅dd什么时候适合复制数据?(或何时分别使用read()和write()部分)以获取更多信息。如果read
系统调用返回少于一个完整的块,则dd
传输一个部分块。它仍然会复制指定数量的块,因此传输的字节总数少于请求的数量。
关于“部分读取”的警告告诉您确切的信息:其中一个读取是部分读取的,因此dd
传输了不完整的块。在块计数中,+1
表示部分读取了一个块。由于输出计数为+0
,因此所有块均被读取读取。
这不会影响数据的随机性:所有dd
写出的字节都是从中读取的字节/dev/urandom
。但是您得到的字节少于预期。
Linux可以/dev/urandom
容纳任意大的请求(来源:extract_entropy_user
in drivers/char/random.c
),因此dd
从它读取时通常是安全的。但是,读取大量数据需要时间。如果该进程收到信号,则read
系统调用将在填充其输出缓冲区之前返回。这是正常现象,应用程序应该read
循环调用。dd
出于历史原因,它不这样做(dd
的起源很模糊,但是它似乎最初是作为一种访问磁带的工具,这种磁带具有特殊的要求,并且从未适合用作通用工具)。当您检查进度时,这会向dd
进程发送一个信号,该信号会中断读取。您可以选择知道多少个字节dd
总共遗嘱副本(确保不中断它-不进行进度检查,不暂停),或知道多少字节dd
到目前为止已复制,在这种情况下,您不知道它将复制多少字节。
dd
GNU coreutils中的版本(在非嵌入式Linux和Cygwin上可以找到)带有一个标志fullblock
,该标志指示dd
调用read
循环(和相同write
),因此始终传输完整的块。错误消息表明您正在使用它。您应该始终使用它(在输入和输出标志中),除非在非常特殊的情况下(通常在访问磁带时)—如果您完全使用它dd
,那就是:通常有更好的解决方案(请参见下文)。
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
确定执行该dd
操作的另一种可能方法是传递一个块大小为1。然后,您可以知道从块计数中复制了多少字节,尽管我不确定read
在读取第一个前a 被中断会发生什么。字节(实际上不太可能,但是可能发生)。但是,即使有效,这也非常慢。
关于使用的一般建议dd
是不要使用dd
。尽管dd
通常将其宣传为访问设备的低级命令,但实际上并非如此:所有魔术都发生在设备文件(/dev/…
)部分中,dd
它只是一个普通的工具,极有可能被滥用,从而导致数据丢失。在大多数情况下,至少在Linux上,有一种更简单,更安全的方法来执行所需的操作。
例如,要读取文件开头的一定数量的字节,只需调用head
:
head -c 1000000m </dev/urandom >file
我在我的机器上进行了快速基准测试,并没有观察到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
如果要查看进度,请致电lsof
以查看文件偏移量。这仅适用于常规文件(示例中的输出文件),不适用于字符设备。
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
您可以致电pv
获取进度报告(优于dd
s),但要牺牲管道中的其他项目(就性能而言,这几乎是不可感知的)。