我有一个两个过程的简单示例
第一个是一个简单的循环,它进行一些处理
#!/bin/bash
function signalHandler() {
echo "sig: $1 received ==> exit"
for i in {1..5}; do
echo "cleanup $i %"
sleep 1
done
trap SIGINT
kill -INT $$
}
trap signalHandler SIGUSR2
for i in {1..100000}; do
echo "doing stuff $i %"
sleep 0.1
done
Run Code Online (Sandbox Code Playgroud)
我像这样启动了脚本:
./script.sh | grep "wow"
Run Code Online (Sandbox Code Playgroud)
我附加了一个辅助 grep 命令只是为了演示。
grep
当我仅向进程 ( )发送 USR2 信号时kill USR2 $(pgrep grep)
,整个管道就会被拆除 (?)。为什么script.sh
不继续了?
其次,当我向整个进程组发送 USR2 信号(类似于kill USR2 -$!
)时,显然会发生同样的情况,因为grep
退出速度很快,它会破坏整个管道而不让script.sh
执行signalHandler
. 我想我有一些误解,这应该如何运作?
多谢
正如 @muru 评论的那样,问题是你的脚本不处理SIGPIPE
.
以下更改将允许脚本按预期终止:
function signalHandler() {
echo "sig: $1 received ==> exit" >&2 # <--
for i in {1..5}; do
echo "cleanup $i %" >&2 # <--
sleep 1
done
trap SIGINT
kill -INT $$
}
trap signalHandler SIGUSR2
trap signalHandler SIGPIPE # <--
Run Code Online (Sandbox Code Playgroud)
为了使示例简单,使用相同的信号处理程序来处理SIGPIPE
. echo
信号处理程序的输出被重定向到,STDERR
因为STDOUT
显然在SIGPIPE
被捕获时已经被破坏了。
输出:
$ ./script.sh | grep wow
./script.sh: line 16: echo: write error: Broken pipe
sig: received ==> exit
cleanup 1 %
cleanup 2 %
cleanup 3 %
cleanup 4 %
cleanup 5 %
User defined signal 2: 31
Run Code Online (Sandbox Code Playgroud)
管道中断(第一条错误消息),但信号处理程序在script.sh
退出之前完成。
如果你想SIGPIPE
完全忽略,你需要为信号添加一个虚拟处理程序,并将主echo
语句的 STDERR 重定向到/dev/null
:
function signalHandler2() {
:
}
trap signalHandler SIGUSR2
trap signalHandler2 SIGPIPE
# ...skip...
for i in {1..100000}; do
echo "doing stuff $i %" 2>/dev/null
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2780 次 |
最近记录: |