포그라운드 프로세스 그룹으로 전송된 터미널 인터럽트에 응답하지 않는 서브쉘 스크립트

포그라운드 프로세스 그룹으로 전송된 터미널 인터럽트에 응답하지 않는 서브쉘 스크립트

일부 보조 스크립트를 제어하는 ​​기본 스크립트가 있습니다. 터미널에서 인터럽트 신호를 보내면 부모는 trap신호를 잡았지만 자식은 잡지 못하고 그 이유를 이해할 수 없습니다. 기본 터미널 설정을 변경하지 않았습니다( stty어디에서도 실행하지 않습니다).

내 상위 및 하위 스크립트와 터미널 출력은 다음과 같습니다.

부모:

#!/bin/sh

./child.sh &

for sig in $(kill -l) ; do
    trap "echo parent:$sig" $sig
done

wait

어린이:

#!/bin/sh

cat < /dev/tty &
PID=$!

for sig in $(kill -l) ; do
    trap "echo child:$sig" $sig
done

wait

터미널 상호작용:

[prompt]$ ./parent.sh
^Cparent:INT
cat: stdin: Input/output error

[prompt]$

고쳐 쓰다

macOS 및 CentOS에서 스크립트를 테스트했는데 위 동작이 발생했습니다. 기본 Bourne 호환 쉘을 사용하여 FreeBSD에서 이것을 테스트할 때 하위 프로세스가 수신하는 신호는 CHLD.

답변1

비대화형 셸에서 비동기적으로 실행되는 명령의 경우(실제로 작업 제어가 활성화되지 않은 경우) POSIX 규정 준수에서 SIGINT 및 SIGQUIT가 무시됩니다.shPOSIX 요구 사항일부 쉘은 이를 무시하지만.

또 다른 POSIX 요구 사항문제는 쉘이 시작될 때 신호가 무시되면 무시할 수 없으므로 망한다는 것입니다.

여기에서는 성가신 "기능"(적어도 현재 버전에서는)이 없는 기능을 대신 사용할 수 있습니다 zsh.sh

그럼에도 불구하고, 쉘에서의 신호 처리는 신뢰성이 가장 낮고 이식성이 떨어지는 측면 중 하나입니다. 동작은 셸마다 그리고 동일한 셸의 서로 다른 버전 간에도 크게 다르다는 것을 알 수 있습니다. 평범하지 않은 것을 시도하려는 경우 심각한 잡아당김과 머리 긁힘을 겪을 준비를 하십시오.

어떤 일이 발생하는지 더 잘 제어할 수 있도록 다른 언어를 사용하는 것이 좋습니다.

또한 나는 가능한 모든 신호를 맹목적으로 처리하지 않고 수신할 것으로 예상하고 처리 방법을 알고 있는 신호만 처리합니다. 예를 들어, SIGCHLD(프로세스를 생성하고 종료를 처리하는 작업이므로 쉘 자체에 관심이 있음)를 포착하면 원하는 대로 작동하지 않을 수 있습니다.

관련 정보