如何防止 dd 的进度在 Linux 上没有意义?

如何防止 dd 的进度在 Linux 上没有意义?

在 Linux 上运行dd复制 ISO 的命令时,我得到一个长时间(很多分钟)保持打开状态的进度打印。然后最后还有另一个。

问题似乎是正在使用一个非常大的缓存,这会混淆dd的输出。

sudo dd bs=4M if=my.iso of=/dev/sdc status=progress

输出(第一行显示很长时间)。

1535115264 bytes (1.5 GB, 1.4 GiB) copied, 1.00065 s, 1.5 GB/s
403+1 records in
403+1 records out
1692844032 bytes (1.7 GB, 1.6 GiB) copied, 561.902 s, 3.0 MB/s

有没有办法防止这种情况发生,以便进度输出有意义?

答案1

从第一行我们可以看出dd一秒钟读取和写入了1.5GB。即使是 SSD 也无法写入那么快。

发生的情况是 /dev/sdc 块设备接受了它(回写),但没有将其发送到磁盘,而是缓冲它并开始以磁盘可以接受的速率写入磁盘。大约 3MiB/s。

系统不能像这样无限期地缓冲数据,它只能接受这么多数据来保存在未提交的数据中肮脏的状态。因此,一段时间后(在您的情况下,在写入超过 1.5GB 但过去了不到 2 秒(因为每秒写入进度行)),ddwrite()系统调用将阻塞,直到数据刷新到磁盘(在此期间它无法写入进度消息)。当它通过时,dd可以发送一些额外丢失的兆字节,并且这发生在不到一秒的时间内,所以你只得到一个额外的进度线。

要查看不同的行为,您可以强制写入同步,即除非数据已提交到磁盘,否则不会返回。例如通过使用oflag=sync or oflag=dsyncor oflag=direct(不过我并不建议这样做)。

答案2

将文件写入块设备时,请使用ddwith oflag=direct。这使用 O_DIRECT 写入,从而避免使用 RAM 作为写回缓存。请注意,为了获得良好的性能,oflag=direct通常需要较大的块大小。

这将避免看到不可能的快速进展,除非你有一个奇怪的设备,它本身有一个非常大的RAM缓存

许多设备都有少量缓存。在这种情况下oflag=direct将显示一个现实的速度的进步。这个更有意义,但是它没有告诉你一切你要知道 :-)。它不保证最后一次写入完成时dd表示已完成。您可以使用该选项确保所有写入均已完成,并检查是否有任何写入错误conv=fsync。这会在最后调用 fsync() 以确保刷新缓存。这是一个例子:

dd if=my.iso of=/dev/sdc oflag=direct bs=4M status=progress conv=fsync

有些人事sync后运行该命令,并且懒得去记住,这是可以理解的conv=fsync。这不太好。 sync不会报告其中一项写入是否失败。

如果设备有非常大的 RAM 缓存,则必须使用oflag=direct,sync.但通常我认为oflag=sync这是性能的潜在障碍。您可能希望进一步增加块大小,以降低缓存刷新的频率。当执行非常同步的 IO 并同时读取多个硬件块时,您可能需要使用双缓冲来保持良好的性能,即使用dd下面链接中的第二个命令。

有时您可能还想从另一个程序(例如gunzip.在这种情况下,良好的性能还取决于iflag=fullblock并通过另一个dd命令进行管道传输。这里的答案中有一个完整的例子:为什么从gunzip到dd管道最后会变慢?

答案3

输出标志oflag=nocache,sync可用于确保内容以恒定速度和恒定缓冲区大小写入驱动器,而不是完全填充到系统缓存中,然后在最后写入:

dd if=/path/to/source.iso of=/path/to/usb-drive bs=4M status=progress oflag=nocache,sync

警告:不要使用较小的块大小,因为这会导致性能降低,并且很可能导致 SSD 运行状况恶化。默认值只是512- 非常低。的值bs=4M应该是合理的。

示范- 使用以下命令进行测试:

# run in background in another terminal window to monitor write cache
while true; do cat /proc/meminfo | grep Dirty; sleep 0.1s; done;

# run without flags (also, needs a manual sync to flush caches in my case)
dd if=/dev/random of=tmp.$(date '+%Y%m%d-%H%M%S') bs=1M count=128 status=progress
sync

# run with oflag=nocache,sync
dd if=/dev/random of=tmp.$(date '+%Y%m%d-%H%M%S') bs=1M count=128 status=progress oflag=nocache,sync

答案4

你使用什么Linux?如果它是基于 Debian 的(Ubuntu、Mint、Debian 等),我会使用一个名为 Disks 的程序。它是一个内置的基于 GUI 磁盘的管理器,可以执行与 DD 相同的操作并为您提供一致的状态。

相关内容