我试图理解该dd
程序的联机帮助页,其中提到:
向正在运行的“dd”进程发送 USR1 信号,使其将 I/O 统计信息打印到标准错误,然后恢复复制。
$ dd if=/dev/zero of=/dev/null& pid=$! $ kill -USR1 $pid; sleep 1; kill $pid
这是什么pid=$!
意思?
这是一个变量的赋值,它获取 pid 吗dd
?并最终用在$pid
变量中?
另外他们为什么使用sleep
and kill
?
这是使用方法吗-USR1
?
答案1
dd if=/dev/zero of=/dev/null&
尾随&
意味着在后台运行前缀命令。 (免责声明:这是过于简单化的陈述)
参考这:
$!是最近的后台命令的PID。
所以pid=$!
分配最近的后台PID到变量pid,即dd
PID。
还有为什么他们使用睡眠和杀戮?
你需要kill $pid
(如果没有指定参数,kill的默认信号是TERM,即进程终止)dd
完成测试后终止进程,否则dd
进程可能会停留在后台并耗尽您的 CPU 资源。检查您平台的系统监视器以查看。
虽然Kill -USR1 $pid
打印 I/O 统计信息,但它不会终止进程。
如果没有睡眠 1 秒,您的进程可能会在有机会将统计输出写入终端之前dd
被最后一个命令语句 ** 终止。kill $pid
这些过程是同步的,但是陷阱+写操作( kill -USR1 $pid
) 可能慢于终止操作( kill $pid
)。所以sleep 1
第二要延迟启动,kill $pid
以确保统计输出完成打印。
这就是-USR1的使用方法吗?
只是man dd
:
向正在运行的“dd”进程发送 USR1 信号,使其将 I/O 统计信息打印到标准错误,然后恢复复制。
和man 7 signal
:
SIGUSR1 30,10,16 Term User-defined signal 1 SIGUSR2 31,12,17 Term User-defined signal 2
结合这两个陈述,你应该明白 USR1 是用户定义信号它的定义是dd
为用户提供一种中断它的方法并且打印 I/O 统计信息在飞行中。它是程序特定的处理程序,并不意味着您可以kill -USR1 other_program_pid
并期望统计输出。
您可能还感兴趣this: 为什么 SIGUSR1 会导致进程终止?。
答案2
这只是一个演示,以说明USR1
信号的使用dd
。
dd if=/dev/zero of=/dev/null &
dd
从后台开始,将数据从/dev/zero
(每当程序读取时产生零)复制到/dev/null
(丢弃写入其中的任何内容)。这提供了一个dd
可用于实验的无害实例——它不会占用任何存储空间,并且只要我们想要它就可以继续运行,这让用户有时间向它发送信号。
pid=$!
将最后一个后台命令 () 的进程标识符存储$!
在变量中pid
。
kill -USR1 $pid
将信号发送USR1
到进程,该进程的标识符是存储在变量中的值,在本例中pid
为后台。dd
当dd
收到此信号时,它会打印出当前进度(读取和写入的数据量)并继续复制。
sleep 1
等一秒钟。
kill $pid
发送TERM
信号至dd
,导致dd
退出。 (让后台运行在这里是没有意义的dd
。)
运行这个而不是上面的第二行会更有指导意义:
kill -USR1 $pid; sleep 1; kill -USR1 $pid; kill $pid
这将输出进度两次,中间间隔一秒,以显示dd
进度;然后dd
不等就杀掉。
对于实际使用,您将为原始dd
命令指定适当的输入和输出,可能还有一些其他选项,并且您不会运行最后一个kill
- 您会等待dd
其自行完成。
USR1
要回答您的最后一个问题,这就是从 shell(或任何其他信号)发送信号的方式:您使用kill
包含要发送的信号以及要将信号发送到的进程的进程标识符(或作业标识符)。您可以使用的其他(非 POSIX)命令是pkill
和killall
,当您想按名称查找进程时。
答案3
对于大多数或所有 shell,$!
是 shell 分叉的最后一个进程的进程 ID(也称为 PID)。该dd
命令使用 进行分叉&
,以便pid=$!
分叉后的右侧将进程 IDdd
分配dd
给 shell 变量pid
。
进程 ID 是 Linux 或 Unix 用来指代其中执行某些代码的地址空间的数字。
该kill
程序的名称不直观,因为其目的是向进程发送信号(小型异步消息)。信号只有几个,大概有128个,都有编号和名称。例如,“kill”信号是数字 9。 USR1 被定义为编号 10。因此,kill -USR1 $pid
将信号 10 发送到编号为 的进程$pid
。dd
有时需要很长时间才能执行,因此几乎可以肯定这就是dd
之前分叉并在后台运行的命令的进程 ID。该kill $pid
命令向同一进程 ID 发送 TERM 信号。 TERM 的意思是“终止”。编写良好的程序通常会捕获 TERM,清理它们分配的资源,然后退出。
我不完全确定为什么你会dd
在后台运行,向其发送 USR1 信号,等待 1 秒,然后导致dd
释放所有资源,然后退出。整个代码片段似乎假设dd
运行很长时间,这可能不是真的。我认为这段代码中存在竞争条件,无论想要什么语义,您可能实际上都无法得到它们。
答案4
如果您希望dd
命令在前台运行并显示当前进度状态。尝试使用status=progress
标志运行命令:
sudo dd if=/dev/sda of=/dev/sdb status=progress
这将动态显示进度。
这是 GNU 实现的扩展dd
(在 2015 年发布的 8.24 版本中添加),dd
自 12.0 (2018) 起也可用于 FreeBSD 上的实现,但通常不包括其他 BSD 上的其他实现。