Gab*_*iel 6 bash process signals exit
我真的很努力去理解我做错了什么,为什么?
我有一个launch.sh
启动process.sh
.
启动文件
#!/bin/bash
while true; do
./process.sh
done
Run Code Online (Sandbox Code Playgroud)
进程文件
#!/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
Run Code Online (Sandbox Code Playgroud)
当我跑
./launch.sh &
Run Code Online (Sandbox Code Playgroud)
然后用它杀死它
kill -s SIGINT -$!
Run Code Online (Sandbox Code Playgroud)
where$!
获取最后一个命令 (launch.sh) 的 PID,减号将信号发送给所有孩子,然后launch.sh
继续。为什么?
我期望以下行为(根据此博客Signal & Bash):
launch.sh
在后台运行脚本的外壳 A被中断,Bash 等待process.sh
完成。由于process.sh
异常返回(出射130)由于在信号处理程序process.sh
,外壳A应该退出。为什么不呢?
如果这个孩子的状态表明它由于那个信号而异常退出,shell 会清理,删除它的信号处理程序,并再次杀死自己以触发操作系统默认操作(异常退出)。或者,它按照陷阱设置运行脚本的信号处理程序,然后继续。
第一,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.
Run Code Online (Sandbox Code Playgroud)
WIFEXITED
检查正常退出,并且WIFSIGNALLED
由于未捕获的信号而终止。由于这些是互斥的,所以 anexit 130
是正常的。
当进程被 SIGINT 终止时,退出状态为 130 是因为 bash 在进程外将其设置为 130,因为它检测到由于 SIGINT 导致的退出:为什么 bash 设置 $?(退出状态)在 Ctrl-C 或 Ctrl-Z 上为非零?
其次,处理 SIGINT 然后死亡的进程应该用 SIGINT 杀死自己。Greg 的 wiki(shell 内容的极好资源)对此有注释:
如果您选择为 SIGINT 设置处理程序(而不是使用 EXIT 陷阱),您应该意识到响应 SIGINT 退出的进程应该使用 SIGINT 杀死自己,而不是简单地退出,以避免给调用者带来问题。因此:
Run Code Online (Sandbox Code Playgroud)trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT
现在,如果您将其更改exit 130
为:
trap - INT
kill -INT $$
Run Code Online (Sandbox Code Playgroud)
你会看到预期的行为。