我非常努力地去理解我做错了什么以及为什么?
我有一个launch.sh
启动的脚本process.sh
。
启动.sh
#!/bin/bash
while true; do
./process.sh
done
进程.sh
#!/bin/bash
function signalHandler() {
for i in {1..2}; do
sleep 0.1s
echo "process.sh: cleanup $i"
done
exit 130
}
trap "signalHandler" "SIGINT"
while true; do
sleep 1s
done
当我跑步时
./launch.sh &
然后用
kill -s SIGINT -$!
其中$!
获取最后一个命令 (launch.sh) 的 PID,减号将信号发送给所有子进程,然后launch.sh
继续。为什么?
我期望以下行为(根据此博客信号与猛击):
后台运行脚本的 shell Alaunch.sh
被中断,Bash 等待process.sh
完成。由于process.sh
中的信号处理程序导致异常返回(退出 130)process.sh
,shell A 应该退出。为什么不呢?
如果该子进程的状态表明它由于该信号而异常退出,则 shell 会进行清理,删除其信号处理程序,并再次终止自身以触发操作系统默认操作(异常退出)。或者,它按照 trap 设置运行脚本的信号处理程序,然后继续。
答案1
首先,exit 130
是不是异常退出。是正常退出,退出状态为130。可以看出man 3 wait
(POSIX):
If the information pointed to by stat_loc was stored by a call to
waitpid() that specified the WUNTRACED and WCONTINUED flags,
exactly one of the macros WIFEXITED(*stat_loc), WIFSIGNALED(*stat_loc),
WIFSTOPPED(*stat_loc), and WIFCONTINUED(*stat_loc) shall evaluate to
a non-zero value.
WIFEXITED
检查正常退出,并WIFSIGNALLED
由于未捕获信号而终止。由于它们是互斥的,所以 anexit 130
是正常的。
当进程因 SIGINT 死亡时,退出状态为 130 是因为 bash 在进程外部将其设置为 130,因为它检测到由于 SIGINT 导致的退出:为什么 bash 设置 $? (退出状态)在 Ctrl-C 或 Ctrl-Z 上变为非零?
其次,处理 SIGINT 然后死亡的进程应该用 SIGINT 杀死自己。 Greg 的 wiki(有关 shell 的优秀资源)有关于此的注释:
如果您选择为 SIGINT 设置处理程序(而不是使用 EXIT 陷阱),您应该意识到响应 SIGINT 而退出的进程应该用 SIGINT 杀死自己而不是简单地退出,以避免给调用者带来问题。因此:
trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT
现在,如果您将其更改exit 130
为:
trap - INT
kill -INT $$
您会看到预期的行为。