「dd(1)」- 转化和复制文件

常用命令

制作 USB 启动盘(常用于系统安装):

dd bs=4M conv=fdatasync if=/path/to/ubuntu-20.04.3-live-server-amd64.iso of=/dev/sdX

语法格式

dd [OPERAND]...

dd OPTION

命令描述

使用可更改的I/O块大小来复制文件,默认情况下从标准输入读取,然后输出到标准输出,并对其执行可选择的转换。

命令选项

命令dd接受下列操作数,其语法受OS/360 JCL的DD(Data Definition,数据定义)语句的启发。

if=file
从文件FILE读取数据,而不是标准输入。

of=file
将输出写入文件FILE而不是标准输出。除非给出’conv=notrunc’,否则dd将文件FILE截断为零字节(或用’seek=’指定的大小)。

ibs=bytes
将输入块大小设置为bytes字节。这使dd的每块会读取bytes字节。默认值是512字节。

obs=bytes
将输出块大小设置为bytes字节。这使dd的每块会输出bytes字节。默认值是512字节。

bs=bytes
将输入和输出块大小都设置为bytes字节。这使dd的每块读取和写入bytes字节,bs会覆盖所有的’ibs’和’obs’设置。另外,如果没有指定数据转换conv选项,则输入也会立即复制到输出,即使读取的输入小于块大小也是如此。

cbs=bytes
将转换块大小设置为bytes字节。将可变长度记录转换为固定长度记录(conv=block)或反过来(conv = unblock)时,使用bytes字节作为固定记录长度。

skip=n
在复制之前,从输入文件中跳过n个’ibs’字节块。如果指定了’iflag=skip_bytes’,则n被解释为字节数,而不是块计数。

seek=n
在复制前,在输出文件中跳过n个’obs’字节块。如果指定了’oflag=seek_bytes’,则n被解释为字节数,而不是块计数。

count=n
从输入文件中复制n个’ibs’字节块,而默认的一直复制到文件结尾。如果指定了“iflag=count_bytes”,则n被解释为字节数,而不是块计数。

请注意,如果输入返回可能短于读取(例如从管道读取时可能会出现这种情况),使用’iflag=fullblock’将确保’count=’对应于完整的输入块,而不是传统的POSIX指定的对输入读取操作进行计数的行为。

status=level
通常在收到’INFO’信号或dd退出时,传送信息才会输出到标准错误中。指定级别level将控制打印的信息量,最后指定的级别level优先级别高。

none’,不要将任何信息或警告消息打印到标准错误中。错误消息正常输出。

noxfer’,不要打印通常构成最后状态行的最终传输速率和卷统计信息。

progress’,在处理每个输入块时,在标准错误上打印传输速率和卷统计信息。统计信息每秒至多输出一行,但在等待I/O时可能会延迟更新。

conv=conversion[,conversion]…
按照转换参数 conversion 指定的文件转换。(在逗号周围没有空格)conversion 可以是下面的值之一:

ascii’,使用POSIX指定的转换表将EBCDIC转换为ASCII。这为所有256字节提供1:1转换。此选项暗含了’conv=unblock’;在尾部空格被删除之前,输入被转换为ASCII。

ebcdic’,将ASCII转换为EBCDIC。这是’ascii’转换的反面。这个选项暗含了’conv=block’;在被转换为EBCDIC之前,会现在尾部添加空格。

ibm’,这就像’conv=ebcdic’一样,除了它使用POSIX指定的替代转换表。这不是1:1的转换,但反映了’~’,'[‘,’]’的常见历史实践。

‘ascii’,’ebcdic’和’ibm’转换是相互排斥的。如果你使用这些选项中的任何一个,则还应该使用’cbs=’选项。

block’,对于输入中的每一行,输出’cbs’字节,根据需要用空格替换输入换行符,并用空格填充。

unblock’,删除每个’cbs’大小的输入块中的任何尾部空格,然后附加一个换行符。

‘block’和’unblock’转换是相互排斥的。

lcase’,将大写字母改为小写。

ucase’,将小写字母改为大写。

‘lcase’和’ucase’转换是相互排斥的。

sparse’,尝试搜索(seek)而不是写NUL输出块。在支持稀疏文件的文件系统上,在扩展输出文件时,这将创建稀疏输出。将此选项与’conv=notrunc’或’oflag=append’结合使用时请小心。使用’conv=notrunc’时,输出文件中那些与输入的NUL块相对应的现有数据将保持不变。用’oflag=seek’执行的搜索将是无效的。同样,当输出是一个设备而不是文件时,NUL输入块不会被复制,因此该选项对于虚拟或预置零设备非常有用。

swab’,交换每对输入字节。与其他不同,GNU的dd在读取奇数个字节时,最后一个字节被简单地复制(因为没有任何可交换的字节)。

sync’,将每个输入块填充为大小为’ibs’且尾部为零的字节。与’block’或’unblock’一起使用时,填充空格,而不是零字节。

以下“conversion”实际上是文件标志,不会影响内部处理:

excl’,如果输出文件已经存在,则失败; dd必须自己创建输出文件。

nocreat’,不要创建输出文件; 输出文件必须已经存在。

‘excl’和’nocreat’转换是相互排斥的。

notrunc’,不要截断输出文件。

noerror’,读取错误后继续。

fdatasync’,在完成输出前同步输出数据。这会强制进行输出数据的物理写入。

fsync’,在完成之前同步输出数据和元数据。这会强制进行输出数据和元数据的物理写入。注意,很多操作都储存在内存中并推迟写入磁盘,该选项告诉 dd 将所有数据写入到磁盘中。

iflag=flag[,flag]…
使用flag参数指定的标志访问输入文件。(在逗号周围没有空格。)

oflag=flag[,flag]…
使用flag参数指定的标志访问输出文件。(在逗号周围没有空格。)下面是可用的flag,但并不是所有的操作系统都支持。

append’,以追加模式写入,因此即使其他进程正在写入该文件,每一次dd的写入都将数据附加到文件的当前内容后。该标志仅适用于输出。如果将此标志与’of=file’操作数结合使用,除非要在输出文件被附加前截断,否则还应指定’conv=notrunc’

cio’,为数据使用并发I/O模式。该模式执行直接I/O,并抛弃POSIX要求以将所有I/O序列化到同一文件中。无法在CIO模式下打开文件的同时,又使用标准打开文件。

direct’,对数据使用直接I/O,避免缓冲区缓存。注意,内核可能会对读取或写入缓冲区大小施加限制。例如,对于ext4目标文件系统和基于Linux的内核,如果输出缓冲区大小不是512的倍数,则使用oflag=direct将导致写入操作失败并显示EINVAL。

directory’,除非文件是一个目录,否则失败。大多数操作系统不允许对目录进行I/O操作,所以此标志的功能有限。

dsync’,为数据使用同步的I/O。对于输出文件,在每次写入时,这会强制进行输出数据的物理写入。对于输入文件,从远程文件读取时,此标志可能很重要,远程文件已由其他进程同步写入。元数据(例如,最后访问时间和最后修改时间)不一定是同步的。

sync’,对数据和元数据使用同步I/O。

nocache’,请求放弃文件的系统数据缓存。当count=0时,指定该文件的所有缓存数据,否则将为该文件已处理部分的缓存丢弃。另外,当count=0时,将诊断丢弃缓存失败,并反映在退出状态中。

请注意,尚未持久存储的数据不会从缓存中丢弃,因此请注意在下面的示例中使用了“sync”选项,这些选项用于最大化“nocache”标志的有效性:

# Advise to drop cache for whole file

dd if=ifile iflag=nocache count=0

# Ensure drop cache for the whole file

dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0

# Advise to drop cache for part of file

# Note the kernel will only consider complete and

# already persisted pages.

dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null

# Stream data using just the read-ahead cache.

# See also the ‘direct’ flag.

dd if=ifile of=ofile iflag=nocache oflag=nocache,sync

nonblock’,使用非阻塞I/O。

noatime’,不要更新文件的访问时间戳。请参阅「文件时间戳」。一些较旧的文件系统默默地忽略了这个标志,因此在使用它之前,在文件上先进行测试是个好主意。

noctty’,不要将该文件分配为dd的控制终端。当文件不是终端时,这不起作用。在许多主机上(例如GNU / Linux主机),这个选项根本没有任何作用。

nofollow’,不解析符号链接指向的目标。

nolinks’,如果文件有多个硬链接,则会失败。

binary’,使用二进制I/O。该选项只对区分二进制文本和文本I/O的非标准平台有效。

text’,使用文本I/O。像’binary’一样,这个选项对标准平台没有影响。

fullblock’,从输入中累积满块。如果满块不可用,read的系统调用可能会提前返回。发生这种情况时,请继续调用read来填充块的其余部分。该标志只能用于iflag。此标志对于管道很有用,因为它们可能会返回短于读取。在这种情况下,需要使用此标志来确保’count=’参数被解释为块数,而不是读操作的计数。

count_bytes’,将’count=’操作数解释为字节数,而不是块计数,它允许指定一个不是I/O块大小倍数的长度。该标志只能用于iflag。

skip_bytes’,将’skip=’操作数解释为字节数,而不是块计数,它允许指定一个不是I/O块大小倍数的偏移量。该标志只能用于iflag。

seek_bytes’,将“seek=”操作数解释为字节计数,而不是块计数,它允许指定一个不是I/O块大小倍数的偏移量。该标志只能用于withlag。

并不是在所有系统中都支持这些标志。在不受支持时,’dd’拒绝使用它们。从标准输入读取或写入标准输出时,不应指定’nofollow’和’noctty’标志,而其他标志(例如’nonblock’)可影响其他进程与受影响文件描述符之间的行为,即使dd退出之后

上面的数值字符串(n和bytes)后面可以跟一个乘数单位:‘b’=512, ‘c’=1, ‘w’=2, ‘xm’=m,或任何标准块大小后缀,像’k’= 1024(参见块大小)。

任何通过‘bs=’, ‘ibs=’, ‘obs=’, ‘cbs=’指定的块大小不应该太大。大于几兆字节的值通常是浪费的,或者是彻头彻尾的反作用或错误诱导,如在GB、EB的情况中。

要处理偏移量或大小不是I/O块大小倍数的数据,可以使用’skip_bytes’,’seek_bytes’,’count_bytes’标志。或者,可以使用独立的dd调用的传统方法。例如,以下shell命令会在磁盘和磁带之间以512 KiB块复制数据,但不要在磁盘开始时保存或恢复4KiB标签:

disk=/dev/rdsk/c0t1d0s2

tape=/dev/rmt/0

# Copy all but the label from disk to tape.

(dd bs=4k skip=1 count=0 && dd bs=512k) <$disk >$tape

# Copy from tape back to disk, but leave the disk label alone.

(dd bs=4k seek=1 count=0 && dd bs=512k) <$tape >$disk

对于发生故障的磁盘,其他工具中有各种额外的功能,以便在磁盘最终死亡之前减少尽可能多的数据保存,例如, GNU的ddrescue。但是,在某些情况下,此类工具不可用,或者管理员对处理dd更加满意。作为一种简单的救援方法,请按以下示例所示调用dd:

# 选项’conv=noerror,sync’用于在读取错误后继续并用NUL填充错误读取,而’iflag=fullblock’用于短读取 (传统上从不会在基于磁盘的设备上发生):

# Rescue data from an (unmounted!) partition of a failing disk.

dd conv=noerror,sync iflag=fullblock </dev/sda1 > /mnt/rescue.img

向正在运行的dd进程发送’INFO’信号(或’USR1’信号不可用),使其将I/O统计信息打印到标准错误,然后继续复制。在下面的例子中,dd在后台运行以复制5GB的数据。kill命令使其输出中间I/O统计信息,当dd正常完成或被SIGINT信号终止时,它会输出最终的统计信息。

# Ignore the signal so we never inadvertently terminate the dd child.

# Note this is not needed when SIGINFO is available.

trap ” USR1

# Run dd with the fullblock iflag to avoid short reads

# which can be triggered by reception of signals.

dd iflag=fullblock if=/dev/zero of=/dev/null count=5000000 bs=1000 & pid=$!

# Output stats every second.

while kill -s USR1 $pid 2>/dev/null; do sleep 1; done

以上脚本将以下列格式输出:

3441325+0 records in

3441325+0 records out

3441325000 bytes (3.4 GB, 3.2 GiB) copied, 1.00036 s, 3.4 GB/s

5000000+0 records in

5000000+0 records out

5000000000 bytes (5.0 GB, 4.7 GiB) copied, 1.44433 s, 3.5 GB/s

‘status=progress’选项会定期更新上面传输统计信息的最后一行。

在缺少’INFO’信号的系统上,dd会响应’USR1’信号,除非设置了POSIXLY_CORRECT环境变量。

附加说明

退出状态

=0 表示成功。
>0 表示失败。

参考文献

man 1 dd, version GNU coreutils 8.28
查看在线手册:http://www.gnu.org/software/coreutils/dd
查看 info 手册:info ‘(coreutils) dd invocation’
What does the conv-fdatasync do in dd command in linux? – Stack Overflow
What is the ‘bs’ option in dd? – Ask Ubuntu