나는 내가 뭘 잘못하고 있는지, 그리고 그 이유가 무엇인지 이해하려고 정말 열심히 노력하고 있습니다.
launch.sh
시작 스크립트 가 있습니다 process.sh
.
start.sh
#!/bin/bash
while true; do
./process.sh
done
process.sh
#!/bin/bash
function signalHandler() {
for i in {1..2}; do
sleep 0.1s
echo "process.sh: cleanup $i"
done
exit 130
}
trap "signalHandler" "SIGINT"
while true; do
sleep 1s
done
내가 달릴 때
./launch.sh &
그런 다음 사용
kill -s SIGINT -$!
마지막 명령(launch.sh)의 PID를 가져 오는 $!
마이너스 기호는 모든 하위 프로세스에 신호를 보낸 다음 launch.sh
계속됩니다. 왜?
나는 다음과 같은 행동을 기대하고 있습니다 (이 블로그에 따르면신호와 슬램):
백그라운드에서 스크립트를 실행하는 셸 A가 launch.sh
중단되고 Bash는 process.sh
완료될 때까지 기다립니다. process.sh
의 신호 처리기가 예외 return(exit 130)을 발생시키기 때문에 process.sh
쉘 A는 종료되어야 합니다 . 왜 안 돼?
하위 프로세스의 상태가 이 신호로 인해 비정상적으로 종료되었음을 나타내면 쉘은 정리하고 해당 신호 처리기를 제거한 다음 다시 자체 종료하여 운영 체제 기본 동작(비정상 종료)을 트리거합니다. 또는 트랩 설정에 따라 스크립트의 신호 처리기를 실행한 다음 계속합니다.
답변1
첫째, exit 130
비정상적으로 종료되었는지 여부입니다. 정상적으로 종료되며 종료 상태는 130입니다. 알 수있는 바와 같이man 3 wait
(POSIX):
If the information pointed to by stat_loc was stored by a call to
waitpid() that specified the WUNTRACED and WCONTINUED flags,
exactly one of the macros WIFEXITED(*stat_loc), WIFSIGNALED(*stat_loc),
WIFSTOPPED(*stat_loc), and WIFCONTINUED(*stat_loc) shall evaluate to
a non-zero value.
WIFEXITED
정상적인 종료를 확인하고 WIFSIGNALLED
포착되지 않은 신호로 인해 종료됩니다. 이들은 상호 배타적이므로 an exit 130
이 정상입니다.
SIGINT로 인해 프로세스가 종료되면 bash는 SIGINT로 인해 종료를 감지하여 프로세스 외부에서 이를 130으로 설정하므로 종료 상태는 130입니다.bash가 $를 설정하는 이유는 무엇입니까? (종료 상태)가 Ctrl-C 또는 Ctrl-Z에서 0이 아닙니까?
둘째, SIGINT를 처리한 다음 종료되는 프로세스는 SIGINT를 사용하여 스스로 종료되어야 합니다. Greg의 wiki(쉘에 대한 훌륭한 자료)에는이에 대한 참고 사항:
EXIT 트랩을 사용하는 대신 SIGINT에 대한 핸들러를 설정하기로 선택한 경우 SIGINT에 대한 응답으로 종료되는 프로세스가SIGINT로 자살하세요발신자에게 문제를 일으키지 않기 위해 단순히 종료하는 것이 아닙니다. 그러므로:
trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT
이제 다음과 같이 변경하면 exit 130
:
trap - INT
kill -INT $$
예상되는 동작을 볼 수 있습니다.