如果我有以下 shell 脚本
sleep 30s
Run Code Online (Sandbox Code Playgroud)
我Ctrl+C在 shell 脚本运行时命中sleep
,它随之消失。
如果我有以下 shell 脚本
sleep 30s &
wait
Run Code Online (Sandbox Code Playgroud)
我Ctrl+C在 shell 脚本运行时命中,sleep
继续,现在父级为 1。
这是为什么?bash 不会传播Ctrl+C给所有孩子吗?
编辑:如果我有以下脚本
/usr/bin/Xvfb :18.0 -ac -screen 0 1180x980x24 &
wait
Run Code Online (Sandbox Code Playgroud)
我在那里生成一个程序,这次Ctrl+C在主Xvfb
进程上也会杀死该进程。
那么如何/为什么Xvfb
与睡眠不同?
在某些进程的情况下,我看到它们被 收割init
,在某些情况下它们会死亡。为什么睡眠会被 init 收获?为什么会Xvfb
死?
mos*_*svy 10
tl;博士; 该Xvfb
过程设置了一个信号处理器SIGINT
和退出时,它接收到这样的信号,但是sleep
过程中没有,所以它继承了“忽略”状态SIGINT
,因为它是通过执行之前运行脚本的外壳设置sleep
二进制。
当 shell 脚本运行时,作业控制被关闭,后台进程(以 开头的那些&
)只是在同一个进程组中运行,SIGINT
并SIGQUIT
设置为SIG_IGN
(忽略)并且它们的标准输入从 重定向/dev/null
。
这是标准要求的:
如果在 shell 执行异步列表时禁用作业控制(参见 set -m 的描述),则列表中的命令应从 shell 继承一个忽略(SIG_IGN)的信号操作,用于 SIGINT 和 SIGQUIT 信号。
如果信号处置设置为SIG_IGN
(忽略),则该状态将通过fork()
和继承execve()
:
在调用进程映像中设置为默认操作(SIG_DFL)的信号应设置为新进程映像中的默认操作。除了 SIGCHLD,调用进程映像设置为忽略的信号 (SIG_IGN) 应设置为新进程映像忽略。
从bash 手册页:
\n\n\n\n\n后台进程是进程组ID与终端\xe2\x80\x99s不同的进程;此类进程不受键盘生成信号的影响
\n
你可以用不同的方式来处理这个问题;首先,杀死列出的作业:
\n\n#!/bin/bash\ntrap \'kill $(jobs -p)\' INT\nsleep 30s &\nwait\n
Run Code Online (Sandbox Code Playgroud)\n\n或者,向同一进程组中的所有进程发送终止命令:
\n\n#!/bin/bash\ntrap \'kill 0\' INT\nsleep 30s &\nwait\n
Run Code Online (Sandbox Code Playgroud)\n