我正在运行一个程序,它(大部分)正确执行,但随后挂起。我想运行该程序,以便一旦它输出某个字符串或停止产生输出,它就会被杀死。
我感兴趣的输出字符串是:
Was exported to:
看到这个输出后,我想自动终止该程序。或者,程序在此之后停止产生输出,因此我可以根据该条件杀死它。我怎样才能实现其中之一?
答案1
Process substitution
一种选择是将此工具作为grep运行。
grep -m 1 "Was exported to:" <(<command>)
告诉-m 1
grep 在第一个匹配后停止运行,一旦停止运行,里面的命令<( ... )
也将被终止。但在我看来,这有点“丑陋”。
仍然使用grep
,但不必运行里面的命令,就是将输出重定向到一个文件,并在后台运行它,然后用 读取该文件tail -F
,grep
输出,以及kill
第一次匹配后的过程。
COMMAND > $OUTPUTFILE & tail --pid=$! -n +1 -F $OUTPTFILE | (grep -q -m 1 "Was exported to:" && kill $!)
这--pid=$!
是为了确保tail
一旦进程完成或终止,它也会停止运行。
grep
但只有当您正在执行的行后面跟着换行符时,这两种方法才有效。
答案2
你可以这样做:
sh -c 'echo "$$"; exec stdbuf -oL "$0" "$@"' my-program with its args | (
IFS= read -r pid &&
sed '/Was exported to:/q' &&
kill -s PIPE "$pid"
)
我们my-program
在与之前运行的进程相同的进程中运行sh
(并将其 pid 发送到管道)stdbuf -oL
(在基于 GNU 或 FreeBSD 的系统上找到),以便恢复基于行的缓冲(应用程序倾向于在以下情况下执行基于块的缓冲):他们的输出不会发送到终端)。
在管道的另一端,sed
等待Was exported to:
和q
uits 第一次出现。之后,向 pid 发送 SIGPIPE 信号,这将导致进程终止。如果没有这个kill
,只有在终止my-program
后向管道写入内容时才会收到 SIGPIPE 。grep