当进程被信号结束时,将输出一条消息,类似于Terminated
或Killed
取决于所使用的信号。是否可以捕获该消息?
以这个示例管道为例:
while true; do timeout 2 sleep 5; done
它没有输出,但是sleep
每 2 秒终止一次。添加一个cat
:
while true; do timeout 2 sleep 5 | cat; done
它现在Terminated
每 2 秒输出一次但cat
看不到它 - 如果我替换cat
为tee somefile
然后文件仍然为空。
我试过2>&1
在命令行的不同地方重定向,但我无法将Terminated
输出放入文件中。
我认为它们是通过libc
链接输出到终端的 shell 而不是循环中的命令。
是否有可能将 theTerminated
和类似的 outout 放入管道中?
(最终,我想将sleep
acurl
和a 替换为cat
一个awk
脚本,该脚本同时处理curl
输出和Terminated
消息。)
分析
是的,它是打印
Terminated
. 如timeout 2 sleep 5 | cat
您所见Terminated
,因为cat
被终止。我的意思是cat
。这在我的另一个答案中有解释。
timeout
将 SIGTERM 发送到其整个进程组,在您的情况下,该组包括sleep
andcat
。过程组
timeout
也包括。它似乎timeout
没有被它自己的信号杀死,这就是 soletimeout 2 sleep 5
不让 shell 打印的原因Terminated
。但是如果你这样做,timeout -s KILL 2 sleep 5
那么你将从Killed
shell 中看到,因为 SIGKILL 既不能被捕获也不能被忽略。当用 SIGKILLtimeout
杀死sleep
时,它也会杀死自己并且 shell 会做出反应。所以你观察到的
cat
才是重要的。Terminated
现在,如果您将 with 替换为sleep
withcurl
,则将终止and 。但这并不重要,因为打印消息的是 shell。如果你真的想捕获消息,那么你需要在shell之后的管道中。cat
awk
timeout
curl
awk
awk
解决方案
如果你真的想捕获消息,那么你需要
awk
在打印消息的 shell 之后的管道中。你需要一个被终止的“受害者”进程,没有它就没有消息。并且您需要一个timeout
在 PGID 等于其 PID 的进程组中运行的 shell,因为这对于该机制至关重要(请参阅链接的答案)。例如awk
,在此管道中应成功处理消息:-i
很重要;没有它timeout
不会杀死我们可怜的谴责cat
。严格来说,它与交互式或非交互式 Bash 无关。它是关于启用作业控制(在交互式 Bash 中默认启用)或禁用(默认情况下在非交互式中)。所以这也将起作用:更优雅的解决方案
有一种更简单的方法来做你想做的事。如果最终你想在脚本中运行它,那么你可以利用解释脚本的 shell 不应该为命令创建单独的进程组这一事实。在非交互式脚本
timeout … | awk
中不会杀死awk
.现在您所需要的只是
timeout -v
告诉您它的作用。以下示例旨在作为非交互式脚本运行。如果你想在交互式 Bash 中测试它,你可以,但你必须先禁用作业控制 (set +m
)。这是脚本:替换
sleep
为curl
。你awk
应该寻找timeout: sending signal TERM to command '…'
而不是试图检测Terminated
。