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

Aby*_*y W 5 shell signals background-process

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

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

         $ dd if=/dev/zero of=/dev/null& pid=$!
         $ kill -USR1 $pid; sleep 1; kill $pid
Run Code Online (Sandbox Code Playgroud)

什么pid=$!意思?

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

还有他们为什么使用sleepkill

这是使用方法-USR1吗?

Fru*_*uit 7

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

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

参考这个

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

所以pid=$!最近的后台PID赋值给变量pid,就是ddPID。

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

您需要kill $pid (如果没有指定参数,kill 的默认信号是 TERM,即进程终止)dd在完成测试后终止进程,否则dd进程可能只是停留在后台并耗尽您的 CPU 资源。检查您平台的系统监视器以查看。

虽然Kill -USR1 $pid打印 I/O 统计信息,但它不会终止进程。

如果没有 sleep 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
Run Code Online (Sandbox Code Playgroud)

结合这两个语句,你应该明白 USR1 是用户定义的信号,它被定义dd为用户可以中断它并即时打印 I/O 统计信息。它是程序特定的处理程序,并不意味着您可以kill -USR1 other_program_pid并期望统计输出。

您也可能对此感兴趣:为什么 SIGUSR1 会导致进程终止?.


Ste*_*itt 6

这只是一个演示来说明USR1信号的使用dd

dd if=/dev/zero of=/dev/null &
Run Code Online (Sandbox Code Playgroud)

dd在后台开始,将数据从/dev/zero(每当程序读取时产生零)复制到/dev/null(丢弃写入的任何内容)。这提供了一个dd可用于试验的无害实例——它不会耗尽任何存储空间,并且会在我们希望的时间内继续运行,这让用户有时间向它发送信号。

pid=$!
Run Code Online (Sandbox Code Playgroud)

将最后一个后台命令 ( $!)的进程标识符存储在变量中pid

kill -USR1 $pid
Run Code Online (Sandbox Code Playgroud)

USR1信号发送到进程,其标识符是存储在pid变量中的值,dd在这种情况下是后台。当dd接收到该信号时,它打印出其当前进展(数据量读取和写入)并继续复制。

sleep 1
Run Code Online (Sandbox Code Playgroud)

等待一秒钟。

kill $pid
Run Code Online (Sandbox Code Playgroud)

TERM信号发送到dd,这将导致dd退出。(让后台dd在这里运行是没有意义的。)

运行它而不是上面的第二行会更有指导意义:

kill -USR1 $pid; sleep 1; kill -USR1 $pid; kill $pid
Run Code Online (Sandbox Code Playgroud)

这将输出两次进度,中间间隔一秒,以显示dd进度;然后dd不用等就杀了。

对于实际使用,您需要为原始dd命令指定适当的输入和输出,可能还有其他一些选项,并且您不会运行最后一个kill——您会等待dd其自行完成。

要回答您的最后一个问题,这就是您USR1从 shell(或任何其他信号)发送信号的方式:您使用kill要发送的信号,以及要发送信号的进程的进程标识符(或作业标识符)到。当您想按名称查找进程时,您可以使用的其他(非 POSIX)命令是pkilland killall