如何在任何程序的命令行中使用/发送信号(例如 dd)

如何在任何程序的命令行中使用/发送信号(例如 dd)

我试图理解该dd程序的联机帮助页,其中提到:

向正在运行的“dd”进程发送 USR1 信号,使其将 I/O 统计信息打印到标准错误,然后恢复复制。

         $ dd if=/dev/zero of=/dev/null& pid=$!
         $ kill -USR1 $pid; sleep 1; kill $pid

这是什么pid=$!意思?

这是一个变量的赋值,它获取 pid 吗dd?并最终用在$pid变量中?

另外他们为什么使用sleepand kill

这是使用方法吗-USR1

答案1

dd if=/dev/zero of=/dev/null&

尾随&意味着在后台运行前缀命令。 (免责声明:这是过于简单化的陈述)

参考

$!是最近的后台命令的PID。

所以pid=$!分配最近的后台PID到变量pid,即ddPID。

还有为什么他们使用睡眠和杀戮?

你需要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为后台。dddd收到此信号时,它会打印出当前进度(读取和写入的数据量)并继续复制。

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)命令是pkillkillall,当您想按名称查找进程时。

答案3

对于大多数或所有 shell,$!是 shell 分叉的最后一个进程的进程 ID(也称为 PID)。该dd命令使用 进行分叉&,以便pid=$!分叉后的右侧将进程 IDdd分配dd给 shell 变量pid

进程 ID 是 Linux 或 Unix 用来指代其中执行某些代码的地址空间的数字。

kill程序的名称不直观,因为其目的是向进程发送信号(小型异步消息)。信号只有几个,大概有128个,都有编号和名称。例如,“kill”信号是数字 9。 USR1 被定义为编号 10。因此,kill -USR1 $pid将信号 10 发送到编号为 的进程$piddd有时需要很长时间才能执行,因此几乎可以肯定这就是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 上的其他实现。

相关内容