假设我正在运行以下保存为hello.sh
的示例
#!/bin/bash
hello() {
echo "hello"
}
trap "hello" INT
sleep 100
echo "end"
并且在shell中我启动CCD_ 2。1秒后,我按下Ctrl-C
。
请将sleep
视为我开始的任何长期过程。
以下是我的问题:
- 生成
SIGINT
时,它是直接传递到sleep
还是传递到shell脚本 - 如果是第二个,我可以让
sleep
有机会处理SIGINT
,并且不传播到其父hello.sh
吗 - 如果是第一个,
hello
功能完成后,sleep
的状态如何
我的测试让我觉得以下是按顺序发生的
sleep
开始运行hello.sh
收到信号- 函数
hello
开始运行 - 功能
hello
完成 echo "end"
开始运行- 脚本退出
但是sleep
过程在哪个阶段退出,以及由于什么原因(例如SIGINT停止了sleep
过程?(
$ cat foo.sh
_sigint()
{
echo "received SIGINT"
}
trap _sigint INT
sleep 10000
echo "status=$?"
$ bash foo.sh # <-- start foo.sh and then press CTRL-C
^Creceived SIGINT
status=130
一些解释:
sleep
作为hello.sh
0的子进程运行。bash
和sleep
在同一进程组中运行,该进程组现在是前台进程组。按下CTRT-C时,它将生成
SIGINT
,信号将发送到前台进程组中的所有进程,因此bash
和sleep
都将接收SIGINT
。根据bash手册(也可以参见
man bash
(如果bash正在等待命令完成并接收到已设置陷阱的信号,则在命令完成之前,陷阱将不会执行。。
所以这里
bash
将等待sleep
被杀死(默认的SIGINT行为是终止进程。参见信号(7((,然后bash
运行其SIGINT
陷阱。根据bash manaul
简单命令的返回值是其退出状态,如果命令由信号
n
终止,则返回值为128+n
。SIGINT
为2(请参阅kill -l
(,因此sleep
的退出状态为128+2=130
。