status=progress 是最直接的实时监控方法,适用于 coreutils ≥ 8.24 的系统,每秒输出已复制量、耗时和速率;旧系统可用 kill -USR1 PID 或 pv 替代。

用 status=progress 最直接(推荐优先试)
现代 GNU coreutils(dd 版本 ≥ 8.24,对应 CentOS 7+/Ubuntu 16.04+)原生支持进度输出,无需额外命令或信号干扰。
只需在命令末尾加上 status=progress:
dd if=/dev/sda of=/backup.img bs=4M status=progress
它会每秒刷新一行类似这样的输出:
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 12.456 s, 172 MB/s
- 该参数默认启用实时速率和已拷贝字节数,不依赖进程信号,无竞态风险
- 如果终端被重定向(如加了
> log.txt),进度仍会输出到 stderr,不影响日志捕获 - 旧系统(如 CentOS 6 或较老的 Debian)不识别该参数,会报错
invalid argument,此时需换方案
向运行中的 dd 发送 SIGUSR1 信号(兼容性最强)
所有主流 Linux 发行版的 dd 都支持接收 SIGUSR1 并打印当前状态,但必须确保 dd 是前台或后台运行中、未被挂起(STOP 状态)。
- 先查
dd进程 PID:pgrep -f "dd.*if="或ps aux | grep "dd" | grep -v grep - 发送信号:
kill -USR1(注意不是PIDkill -SIGUSR1) - 效果:立即在
dd原始终端打出一行当前进度(同status=progress格式) - 想自动刷新?用
watch -n 2 kill -USR1,每 2 秒触发一次PID
⚠️ 常见失败点:用 killall -USR1 dd 可能误杀其他名字含 dd 的进程;pkill -USR1 "^dd$" 更安全,但需确保正则匹配准确。
用 pv 替代或包裹 dd(适合大文件/管道场景)
当 dd 用于管道(如 dd if=image.iso | gzip > out.gz)或你想获得更丰富的进度条(ETA、瞬时速率曲线),pv 是更可控的选择。
安装后直接替换或插入:
dd if=/dev/sda bs=4M | pv -s $(blockdev --getsize64 /dev/sda) | dd of=/backup.img bs=4M
-
-s参数告诉pv总大小,从而计算 ETA;blockdev --getsize64获取设备字节总数 - 若源是普通文件,可用
stat -c "%s" file替代 -
pv本身不修改数据,只透传并统计,比反复发信号更稳定 - 缺点:多一层进程,轻微性能开销(通常可忽略);需要额外安装
pv(apt install pv/yum install pv)
为什么 watch -n 1 pkill -USR1 ^dd$ 有时没反应?
这个常用命令看似简洁,但有几个隐蔽陷阱:
-
pkill默认匹配整个命令行,^dd$只匹配纯dd进程(不含参数),实际几乎不存在——应改用pkill -f "dd.*if=" - 部分系统(如某些 Alpine 容器)的
pkill不支持-f,得退回到ps | grep | awk | kill组合 - 如果
dd运行在非交互式 shell(如 systemd service、cron)中,SIGUSR1输出可能被丢弃,看不到进度 - 多个
dd并行时,killall dd会全部触发,干扰判断
真正稳的写法是:先固定 PID,再循环发信号,且始终重定向 stderr 到可见位置。











