현재 실행 중인 하위 프로세스가 SIGINT를 처리하는 경우 Bash가 이를 무시하는 이유는 무엇입니까?

현재 실행 중인 하위 프로세스가 SIGINT를 처리하는 경우 Bash가 이를 무시하는 이유는 무엇입니까?

다음 Bash 루프를 다음과 같이 중단하면 ^C:

(while true; do sleep 5; done)

그러나 다음의 경우에는 그러하지 않습니다.

(while true; do aplay test.wav; done)

내가 아는 한, 차이점은 aplaycatch와 핸들러 SIGINT의 차이입니다 sleep.

왜 이런거야? POSIX는 이 동작을 어딘가에 지정합니까(Dash가 동일한 작업을 수행하는 것으로 나타났습니다). 그렇다면 그 이유는 무엇입니까? 왜 이런 행동이 바람직한지 잘 모르겠습니다. 실제로 Bash는 어떻게 차이점을 구분할 수 있습니까? 나는 한 프로세스가 다른 프로세스에게 신호 처리 방법을 알려줄 수 있는 메커니즘(적어도 ptrace해커 제외)을 모른다는 점을 인정해야 합니다 ./proc/

또한, 이를 상쇄할 수 있는 방법은 없을까요? 나는 trap 'exit 0' SIGINTbefore 루프도 도움이 되지 않는다는 것을 알았습니다.

(편집하다: 하위 쉘에서 루프를 실행하는 것이 중요합니다. 그렇지 않으면 상위 쉘이 루프를 수신하지 않기 때문입니다 SIGINT. )

답변1

문제가 잘 설명되어 있습니다여기, 처럼세계교육협의회 기다렸다가 협력하여 종료하세요.꼭 읽어보시길 권합니다. 기본적으로 신호는 모든 포그라운드 프로세스(예: 쉘 및 프로그램, 절전 또는 재생)에서 수신됩니다. 프로그램이 신호를 처리하지 않으면 코드 130으로 종료됩니다. 쉘은 자식 프로세스가 완료될 때까지 기다리고 이를 보고 실제로 신호를 수신하면 종료됩니다.

프로그램이 신호를 포착하면 일반적으로 코드 1(aplay와 동일)로 종료됩니다. 쉘이 자식 프로세스를 기다릴 때 신호로 인해 종료되지 않았음을 발견하므로 신호가 프로그램 작업의 정상적인 측면이라고 가정해야 쉘이 정상적으로 작동합니다.

예를 들어, aplay를 처리하는 가장 좋은 방법은 반환 코드가 0이 아닌지 확인하고 중지하는 것입니다.

(while aplay test.wav; do :; done)

위의 기사에서는 정리를 수행하기 위해 sigint를 포착하려는 선의로 동작하는 프로그램이 해당 핸들러를 비활성화하고 올바른 종료 플래그 세트를 얻기 위해 스스로를 다시 종료해야 한다고 설명합니다.

답변2

스크립트는 하위 프로세스가 완료될 때까지 신호를 받지 않습니다. 하지만 백그라운드에서 실행한 다음 기다리면 상위 프로세스가~ 할 것이다신호를 받으세요:

(while true; do aplay test.wav; done) &
wait $!

답변3

이것을 시도해 볼 수 있습니다. 저는 이 문제를 몇 번 겪었는데 왜 작동하는지 모르겠습니다.

$(sigint)

이는 bash의 var와 같은 결과를 표시하기 위한 것이지만 그렇게 하려면 실행해야 하며 때로는 작동합니다.

관련 정보