Linux运行dd时得到进度和速度

本文同步自(最佳显示效果请点击):https://zohead.com/archives/dd-progress-speed/

我们常在 Linux 系统中使用 dd 命令做文件或设备的读取和写入操作,只是 dd 对读写进度和速度显示不是实时的,下面以两个磁盘设备之间的备份为例说明两种如何在 dd 命令运行过程中得到进度和速度的方法。

1、通过 dd 的信号得到进度和速度:

新的 Linux 系统中的 dd 命令支持在运行过程中接收 SIGUSR1 用户信号并显示当前实际读写了多少数据以及统计的平均速度是多少。

假设测试的是从 /dev/sdc 设备拷贝 360GB 的数据到 /dev/sdb 裸设备中:

dd if=/dev/sdc of=/dev/sdb bs=1024k count=360000

然后切换到另一个 shell 中查看 dd 的 PID,并发送 SIGUSR1 信号:

~ # ps ax | grep dd
    2 ?        S      0:00 [kthreadd]
 5520 pts/1    D+     0:01 dd if=/dev/sdc of=/dev/sdb bs=1024k count=360000
 5534 pts/0    R+     0:00 grep dd
~ #
~ # kill -USR1 5520
~ # sleep 30
~ # kill -USR1 5520

再次切换到 dd 命令运行的 shell 上,就可以看到产生的两个 dd 命令的进度和速度输出,此时 dd 命令仍在运行中:

3226+0 records in
3225+0 records out
3381657600 bytes (3.4 GB) copied, 28.6073 s, 118 MB/s

6538+0 records in
6537+0 records out
6854541312 bytes (6.9 GB) copied, 58.0373 s, 118 MB/s

通过 SIGUSR1 得到的输出中显示是已拷贝的字节数、花费的时间和平均速度。

2、通过 lsof 命令得到进度和速度:

对于不支持 SIGUSR1 信号的 dd 命令或者其它系统来说,我们也可以使用 lsof 命令间接的来得到 dd 的进度和速度。

首先运行同样的拷贝硬盘的 dd 命令,检查 dd 命令的 PID,然后就可以使用 lsof 命令的 -p 选项指定 PID 查看 dd 命令打开的所有句柄:

~ # ps ax | grep dd
    2 ?        S      0:00 [kthreadd]
 4420 pts/0    D+     4:29 dd if /dev/sdc of /dev/sdb bs 1024k count 360000
 4987 pts/1    S+     0:00 grep dd

~ # lsof -p 4420
COMMAND  PID USER   FD      TYPE DEVICE     SIZE/OFF  NODE NAME
dd      4420 root  cwd       DIR  253,0         1024     2 /
dd      4420 root  rtd       DIR  253,0         1024     2 /
dd      4420 root  txt   unknown                           /proc/4420/exe
dd      4420 root  mem       REG  253,0       139336 58494 /lib64/ld-2.12.so
dd      4420 root  mem       REG  253,0        17816 38359 /lib64/libdl-2.12.so
dd      4420 root  mem       REG  253,0      1635256 38319 /lib64/libc-2.12.so
dd      4420 root  mem       REG  253,0       542112 58483 /lib64/libm-2.12.so
dd      4420 root  mem       REG  253,0        13760 58547 /lib64/libpam_misc.so.0.82.0
dd      4420 root  mem       REG  253,0        95016 58477 /lib64/libaudit.so.1.0.0
dd      4420 root  mem       REG  253,0        55280 38331 /lib64/libpam.so.0.82.2
dd      4420 root  mem       REG  253,0       387880 38325 /lib64/libfreebl3.so
dd      4420 root  mem       REG  253,0        38256 58471 /lib64/libcrypt-2.12.so
dd      4420 root    0r      BLK   8,32 0x3814900000  1125 /dev/sdc
dd      4420 root    1w      BLK   8,16 0x3814900000  1154 /dev/sdb
dd      4420 root    2u      CHR  136,0          0t0     3 /dev/pts/0

从上面的 lsof 输出可以看到,NAME 列出的有 dd 命令打开的 /dev/sdc 和 /dev/sdb 两个设备句柄,SIZE/OFF 列出的就是这两个句柄对应的文件大小和偏移量,由于设备句柄没有直接的文件大小,这里只显示了偏移量(从 0 字节开始,单位为字节,16 进制形式显示)。

这样我们可以直接计算出 dd 命令的进度(这里是直接以 360GB 的数据量来计算的,实际使用时需要修改,并且需要考虑到初始时是否有偏移量等问题):

~ # lsof -p 4420 | gawk '{if ($NF=="/dev/sdc") {print strtonum($(NF-2))*100/(360000*1048576)" %";}}'
88.5208 %

上面的 88.5208% 就是 dd 的进度,同样我们使用延时计算的方法可以得到 dd 的当前实时速度:

~ # (lsof -p 4420 && sleep 5 && lsof -p 4420) | gawk '{if ($NF=="/dev/sdc") {printf strtonum($(NF-2))" ";}}' | gawk '{print ($2-$1)/1048576/5;}'
96.2

这里采取间隔 5 秒钟调用一次 lsof 命令,然后使用 gawk 命令截取 lsof 输出中的偏移量并计算速度,实际速度以 MB/s 形式进行显示。

本文只是针对 dd 命令专门写的得到进度和速度的方法,相对而言第一种方法比较简单,而第二种方法可以做到不依赖 dd 命令的版本而且可以实时统计当前的实际速度,实际使用时有任何问题欢迎提出指正哦。

发表评论





*