캡처 신호를 보내면 POSIX 셸에서는 "읽기"가 반환되지만 Bash에서는 반환되지 않는 이유는 무엇입니까?

캡처 신호를 보내면 POSIX 셸에서는 "읽기"가 반환되지만 Bash에서는 반환되지 않는 이유는 무엇입니까?

신호를 기다리면서 백그라운드에서 유휴 상태로 있는 쉘 스크립트를 작성하려고 합니다. 스크립트가 사용자 입력을 허용하지 않기 때문에 read기다리는 동안 스크립트를 무기한 차단 하고 싶습니다 .

Bash에서 다음 코드는 예상대로 작동하는 것으로 보이며 SIGUSR1이 수신될 때마다 "신호"를 출력합니다.

#!/bin/bash
trap "echo signal" SIGUSR1
read
$ ./test
signal
signal
...

그러나 BusyBox ash를 사용하여 실행하는 경우 #!/bin/shSIGUSR1을 보내면 프로그램이 종료됩니다.

#!/bin/sh
trap "echo signal" SIGUSR1
read
$ ./test
signal
$

read표준 입력에서 EOF 또는 IFS를 읽은 후에만 반환 하면 안 되나요 ? 이 경우에는 그런 일이 발생하지 않습니다. 그러면 반환되는 원인은 무엇입니까?

답변1

Dash와 BusyBox는 POSIX 사양을 준수하므로 신호가 read즉시 종료될 수 있습니다. Bash는 다음 경우를 제외하고는 그렇지 않습니다.POSIX 모드. 이 섹션은 다음과 같습니다.신호상태

쉘이 유틸리티의 포그라운드 명령 실행이 완료되기를 기다리는 동안 트랩 세트 신호가 수신되면 해당 신호와 연관된 트랩은 포그라운드 명령이 완료될 때까지 실행되지 않습니다.

read하나도 아니야특수 내장, 동일한 프로세스 내에서 실행되는 경우에도 "포그라운드 명령으로 실행되는 유틸리티"입니다. 이는 트랩을 실행하고 실행을 계속하는 bash 동작을 제거합니다 read.

이 섹션은 다음과 같습니다.실행 환경유틸리티를 실행할 때 신호가 작동하는 방식을 명확하게 했습니다(비특수 내장 기능도 포함).

유틸리티가 셸 스크립트인 경우 셸에서 포착한 트랩은 기본값으로 설정되어야 하며 셸에서 무시되는 트랩은 유틸리티 무시로 설정되어야 합니다. 유틸리티가 셸 스크립트가 아닌 경우 트랩 작업(기본값 또는 무시)은 다음과 같이 설정되어야 합니다. 유틸리티의 적절한 신호 처리 작업에 매핑됨

내장 스크립트는 쉘 스크립트는 아니지만 여전히 스크립트를 실행하는 쉘의 일부로 실행된다고 할 수 있으므로 첫 번째 절을 적용할 수 있습니다. 그러나 두 동작 모두 유틸리티가 상위 트랩을 실행하는 것을 허용하지 않습니다. 가능한 유일한 동작은 read신호를 무시하거나 차단하거나 즉시 반환하도록 하는 것입니다. 설명read신호에 대한 언급이 없으므로 표준 신호에 대한 마스크 변경은 허용되지 않으며 무시할 수 없습니다. read틀림없이 완료될 때까지 신호를 차단할 수 있습니다(프로그램은 내부 목적을 위해 일시적으로 신호를 차단할 수 있습니다). 그러나 이는 read입력을 기다리는 동안 SIGINT를 차단하지 않으려는 바람과 충돌합니다(Occam의 면도날은 그렇게 하는 것이 의미가 없다고 말합니다). SIGINT의 경우 이 동작입니다. 따라서 readSIGUSR1(mksh가 작동하는 방식)에서 아무것도 하지 않는 것은 기술적으로 규정을 준수할 수 있지만 합리적인 행동이라고 생각하지 않습니다.

Dash와 BusyBox는 POSIX와 완전히 호환되지 않습니다. 신호에 의해 중단되면 둘 다(Ubuntu 22.04 기준) $?1로 설정됩니다.read종료 상태.

신호 수신으로 인해 종료되는 명령은 128보다 큰 종료 상태를 보고해야 합니다.

(실제로는 ATT ksh가 256+신호값인 것을 제외하고는 128+신호값입니다.)

관련 정보