Bash에서 프로세스 그룹을 시작합니다. 그런 다음 전체 프로세스 그룹에 SIGINT를 보냅니다. 때때로 SIGINT는 프로세스를 종료하지만 때로는 그렇지 않습니다. SIGINT가 때때로 무시되는 이유는 무엇입니까?
프로세스 그룹이 백그라운드에서 시작되었는지, bash 쉘의 중첩, Mac/Linux 운영 체제에 따라 다른 동작이 나타납니다. 누구든지 이것에 대해 밝힐 수 있다면 매우 감사하겠습니다.
다음 예에서는 Python 실행 파일을 사용합니다.sleep_in_pgrp.py
#!/usr/bin/env python2.7
import os;
import subprocess
os.setpgrp();
subprocess.check_call(["sleep","10000"]);
프로세스 그룹을 생성하고 절전 모드를 시작합니다. 관찰된 현상은 Python과 관련이 없어야 합니다. 나는 bash에 명령이나 내장 기능이 없기 때문에 Python을 사용하고 있습니다 setpgrp
.고쳐 쓰다: 분명히 대화형 쉘을 실행하여새로운 프로세스 그룹
1) 백그라운드에서 프로세스 그룹을 시작하고 리더를 기다립니다. SIGINT는 무시됩니다.
다음 명령을 실행합니다.
$ bash -c ' { sleep_in_pgrp.py; } & wait $! '
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
SIGINT'ing Python의 프로세스 그룹프로세스를 종료하지 마십시오. 이유는 무엇입니까?
$ sudo kill -s SIGINT -- -2965
2) 포그라운드에서 프로세스 그룹을 시작합니다. 신호 지능이 작동합니다.
을 제거하면 & wait $!
SIGINT는 예상대로 프로세스 그룹을 종료합니다. 이유는 모르겠지만 이 경우 SIGINT가 프로세스를 종료했다는 사실은 놀랍지 않습니다.
$ bash -c ' { sleep_in_pgrp.py; } '
다른 터미널에서:
$ 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
SIGINT는 프로세스 그룹을 종료합니다.
$ sudo kill -s SIGINT -- -3353
3) 백그라운드에서 Python을 실행하는 동안 하위 쉘을 제거하십시오. 신호 지능이 작동합니다.
쉘 중첩이 여기서 동작에 영향을 미친다는 사실에 매우 놀랐습니다. 나는 어떤 설명도 생각할 수 없습니다.
bash -c
처음에 제거했습니다 .
$ { sleep_in_pgrp.py; } & wait $!
다른 터미널에서:
$ 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
SIGINT는 프로세스 그룹을 종료합니다.
$ sudo kill -s SIGINT -- -2507
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
이제 Mac의 하위 쉘에서 배경 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
Mac의 경우:
$ bash -c ' { sleep_in_pgrp.py; } & wait $! '
다른 터미널에서:
$ 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
이 경우 SIGINT는 프로세스 그룹도 종료합니다.
$ sudo kill -s INT -18743
CentOs7의 Bash 버전은 다음과 같습니다.
$ echo $BASH_VERSION
4.2.46(2)-release
Mac에서는 bash 버전이
$ echo $BASH_VERSION
4.4.12(1)-release
이것답변설명 + 프로세스 그룹에 SIGINT를 보내는 Ctrl방법입니다 . C이것이 바로 프로세스 그룹에 SIGINT를 보내서 여기서 하려는 작업입니다. 이것답변비대화형 작업에는 SIGINT 처리기가 필요하다고 언급했습니다. 내가 보고 있는 다른 행동을 설명하는 것이 확실하지 않습니다. 또한 백그라운드 프로세스를 기다리는 것이 해당 프로세스에 대한 SIGINT 처리에 영향을 미치는지 알고 싶습니다.
답변1
이 프로세스는 다른 기능과 함께 사용하기 위해 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;
}
이 프로그램에서 신호 2를 잡는 것은 mysignal 함수 또는 다른 것을 호출하는 것입니다. 프로세스를 종료하는 대신 변수 값을 변경하기만 하면 됩니다.
그러면 이 프로세스는 SIGINT에 의해 종료되지 않습니다.
답변2
kill -INT pid
" " 또는 " kill -INT -- -pgid
" 또는 - 에 의해 Ctrl전송된 SIGINT는 C항상 포그라운드 프로세스(포그라운드 프로세스 그룹)에 영향을 미칩니다. &로 비동기적으로 시작된 모든 항목은 INT의 영향을 받지 않습니다(명령 대체와 같이 백그라운드에서 실행되는 하위 쉘은 제외) (cmd;cmd, ...etc ) &
. $(cmd) &
).
잊지 마세요: bash는 WCE(Wait and Cooperative Exit)를 구현합니다. 즉, 상위 프로세스는 SIGINT를 통해 하위 프로세스가 완료될 때까지 기다린 다음 Ctrl하위 C프로세스가 SIGINT를 통해 종료되는 경우에만 종료하기로 결정합니다.
나보다 더 나은 설명은https://www.cons.org/cracauer/sigint.html