나는 그것으로부터 배웠다https://unix.stackexchange.com/a/230568/674SIGINT 수신 시 0으로 종료하면 ping
해당 명령이 포함된 bash 스크립트가 ping
종료되는 대신 계속 실행될 수 있습니다.
비슷한 동작을 하는 스크립트가 있습니다.
#!/bin/bash
while true; do
sudo -S sleep 4;
echo $?
sudo -k;
done
실행할 때 비밀번호를 묻는 메시지가 나타나면 Ctrl-C를 입력하면 스크립트가 종료되지 않고 계속 실행됩니다. 유일한 차이점은 sudo
SIGINT를 받은 후 0이 아닌 1로 종료된다는 것입니다. 그렇다면 bash 스크립트가 종료되지 않고 계속 실행되는 이유가 궁금합니다. 감사해요.
$ ./test.sh
[sudo] password for t:
1
[sudo] password for t:
1
[sudo] password for t:
1
...
답변1
이 테스트는 단순한 "명령이 성공했는지" 테스트가 아닙니다. 프로세스가 SIGINT로 종료되면 종료 상태는 다음으로 읽을 수 있습니다.wait(2)
. WIFSIGNALED
and 를 사용하면 WTERMSIG
bash는 하위 프로세스(이 경우 sudo)가 신호에 의해 직접 종료되었는지 여부를 확인할 수 있습니다.
Ctrl+C를 눌렀을 때의 시스템 호출 결과는 다음과 같습니다 cat
(에 따라 strace
).
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGINT}], 0, NULL) = 9357
다음에서 Ctrl+C를 눌렀을 때의 결과입니다 sudo -S sleep 4
.
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 1}], 0, NULL) = 9479
완전성을 위해 Ctrl+C'ing의 결과는 다음과 같습니다 ping localhost
.
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 9710
답변2
분명히 명령은 INT 신호를 처리하여 예 sudo
를 들어 종료되도록 합니다. sleep
따라서 Bash는 SIGNIT의 기본 핸들러에서 스스로를 종료해야 한다고 생각하지 않습니다.
bash는 SIGINT/SIGQUIT 패스를 처리할 때 대기 및 협력 종료 방법을 구현하는 몇 안 되는 쉘 중 하나입니다. 스크립트가 해석되면 SIGINT를 수신하자마자 즉시 종료되지 않지만 현재 실행 중인 명령이 반환될 때까지 기다리고 해당 명령도 해당 SIGINT에 의해 종료되는 경우에만 종료됩니다(SIGINT로 자체 종료). 예를 들어, 스크립트가 vi를 호출하고 vi에서 Ctrl+C를 눌러 작업을 취소하는 경우 이는 스크립트 중단 요청으로 간주되어서는 안 됩니다.
SIGINT 트랩을 정의하여 이 동작을 재정의할 수 있습니다.
trap 'trap - INT; kill -s INT $$' INT
인용하다:https://mywiki.wooledge.org/SignalTrap(4장과 5장)