Hak*_*aba 5 shell bash signals centos macos
我从 bash 启动了一个进程组。然后我将 SIGINT 发送到整个进程组。有时 SIGINT 会杀死进程,有时不会。为什么 SIGINT 有时会被忽略?
根据进程组是否在后台启动、bash shell 的嵌套以及 Mac/Linux 操作系统,我看到不同的行为。如果有人能对此有所了解,我将不胜感激。
在以下示例中,我使用这个名为的 python 可执行文件 sleep_in_pgrp.py
#!/usr/bin/env python2.7
import os;
import subprocess
os.setpgrp();
subprocess.check_call(["sleep","10000"]);
Run Code Online (Sandbox Code Playgroud)
它创建一个进程组并开始睡眠。观察到的现象应该与python无关。我使用 python 只是因为 bash 没有setpgrp
命令或内置命令。更新:显然也可以运行一个交互式 shell 来创建一个新的进程组
1)在后台启动进程组,等待leader。SIGINT 被忽略。
执行以下命令:
$ bash -c ' { sleep_in_pgrp.py; } & wait $! '
Run Code Online (Sandbox Code Playgroud)
Bash 在后台启动 python 并等待它。在另一个终端:
$ ps -Heo pid,ppid,tpgid,pgid,sid,user,args
PID PPID TPGID PGID SID COMMAND
2507 1574 2963 2507 2507 -bash
2963 2507 2963 2963 2507 bash -c { sleep_in_pgrp.py; } & wait $!
2964 2963 2963 2963 2507 bash -c { sleep_in_pgrp.py; } & wait $!
2965 2964 2963 2965 2507 python2.7 ./sleep_in_pgrp.py
2966 2965 2963 2965 2507 sleep 10000
Run Code Online (Sandbox Code Playgroud)
SIGINT'ing the proccess group of python不会杀死任何进程。可能是什么原因?
$ sudo kill -s SIGINT -- -2965
Run Code Online (Sandbox Code Playgroud)
2)在前台启动进程组。SIGINT 有效。
如果我删除& wait $!, SIGINT 会按预期终止进程组。我不知道为什么,但我并不感到惊讶 SIGINT 在这种情况下杀死了进程。
$ bash -c ' { sleep_in_pgrp.py; } '
Run Code Online (Sandbox Code Playgroud)
在另一个终端:
$ ps -Heo pid,ppid,tpgid,pgid,sid,user,args
PID PPID TPGID PGID SID COMMAND
2507 1574 3352 2507 2507 -bash
3352 2507 3352 3352 2507 bash -c { sleep_in_pgrp.py; }
3353 3352 3352 3353 2507 python2.7 ./sleep_in_pgrp.py
3354 3353 3352 3353 2507 sleep 10000
Run Code Online (Sandbox Code Playgroud)
SIGINT 杀死进程组。
$ sudo kill -s SIGINT -- -3353
Run Code Online (Sandbox Code Playgroud)
3)在后台运行python时删除子shell。SIGINT 有效。
我很惊讶 shell 嵌套会影响这里的行为。我想不出任何解释为什么。
我bash -c在开始时删除了:
$ { sleep_in_pgrp.py; } & wait $!
Run Code Online (Sandbox Code Playgroud)
在另一个终端:
$ ps -Heo pid,ppid,tpgid,pgid,sid,user,args
PID PPID TPGID PGID SID COMMAND
2507 1574 2507 2507 2507 -bash
3488 2507 2507 3488 2507 -bash
3489 3488 2507 3489 2507 python2.7 ./sleep_in_pgrp.py
3490 3489 2507 3489 2507 sleep 10000
Run Code Online (Sandbox Code Playgroud)
SIGINT 杀死进程组。
$ sudo kill -s SIGINT -- -2507
Run Code Online (Sandbox Code Playgroud)
4) 在 Mac 中运行第一条命令:SIGINT 有效。
前 2 个命令在 CentOs7 虚拟机中运行。
$ uname -a
Linux ip-10-229-193-124 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 13 10:46:25 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
我现在在 mac 的子 shell 中使用后台 python 执行第一个命令。
$ uname -a
Darwin mbp-005063 15.6.0 Darwin Kernel Version 15.6.0: Sun Jun 4 21:43:07 PDT 2017; root:xnu-3248.70.3~1/RELEASE_X86_64 x86_64
Run Code Online (Sandbox Code Playgroud)
在 Mac 中:
$ bash -c ' { sleep_in_pgrp.py; } & wait $! '
Run Code Online (Sandbox Code Playgroud)
在另一个终端:
$ PID PPID TPGID PGID SESS COMMAND
18741 40096 18741 18741 0 bash -c { sleep_in_pgrp.py; } & wait $!
18742 18741 18741 18741 0 bash -c { sleep_in_pgrp.py; } & wait $!
18743 18742 18741 18743 0 /usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python ./sleep_in_pgrp.py
18744 18743 18741 18743 0 sleep 10000
40094 2423 18741 40094 0 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server /usr/bin/login -fpl hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
40095 40094 18741 40095 0 /usr/bin/login -fpl hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
40096 40095 18741 40096 0 -bash
-+= 00001 root /sbin/launchd
\-+= 02423 hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2
\-+= 40094 hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --server /usr/bin/login -fpl hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
\-+= 40095 root /usr/bin/login -fpl hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
\-+= 40096 hbaba -bash
\-+= 18741 hbaba bash -c { sleep_in_pgrp.py; } & wait $!
\-+- 18742 hbaba bash -c { sleep_in_pgrp.py; } & wait $!
\-+= 18743 hbaba /usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python ./sleep_in_pgrp.py
\--- 18744 hbaba sleep 10000
Run Code Online (Sandbox Code Playgroud)
在这种情况下,SIGINT 也会杀死进程组
$ sudo kill -s INT -18743
Run Code Online (Sandbox Code Playgroud)
CentOs7 中的 Bash 版本是
$ echo $BASH_VERSION
4.2.46(2)-release
Run Code Online (Sandbox Code Playgroud)
在 Mac 中,bash 版本是
$ echo $BASH_VERSION
4.4.12(1)-release
Run Code Online (Sandbox Code Playgroud)
这个答案解释了Ctrl+如何 C将 SIGINT 发送到进程组。这就是我在这里尝试将 SIGINT 发送到进程组的目的。这个答案提到非交互式作业需要 SIGINT 处理程序。我不确定它解释了我看到的不同行为。我还想知道等待后台进程是否会影响该进程的 SIGINT 处理。
该进程很可能捕获 SIGINT 信号以与其他函数一起使用。
仅当接收到的信号未知时,该进程才会死亡。但是,如果进程设置了一个链接到该信号的函数,它就不会死,除非链接到该信号的函数完成程序。
例如,一个简单的 C 程序:
#include <signal.h>
int sigreceived = 0;
void mysignal();
int main(){
signal(2, mysignal); //SIGINT corresponds to 2 signal
while(1);
return 0;
}
void mysignal(){
sigreceived=1;
}
Run Code Online (Sandbox Code Playgroud)
在这个程序中,捕获信号2是为了调用mysignal函数什么的,而不是杀死进程,只需更改一个变量的值
然后,这个进程不会被 SIGINT 杀死