스테판 차젤라스의 답장https://unix.stackexchange.com/a/230568
이상적으로는 SIGINT에서 사망했음을 부모에게 보고하고 싶습니다(따라서 다른 bash 스크립트인 경우 해당 bash 스크립트도 중단됩니다).130을 종료하는 것은 SIGINT로 죽는 것과는 다릅니다.(일부 쉘은 $?를 두 경우 모두 동일한 값으로 설정하지만) 일반적으로 SIGINT를 통해 사망을 보고하는 데 사용됩니다(SIGINT가 2인 시스템에서는 이것이 가장 많습니다).
하지만이는 bash, ksh93 또는 FreeBSD sh에서는 작동하지 않습니다. SIGINT는 130 종료 상태를 사망으로 처리하지 않습니다.그리고 상위 스크립트는 거기서 끝나지 않습니다.
- "130으로 나가는 것은 SIGINT로 죽는 것과 다르다"는 점에서 차이점은 무엇입니까?
- 왜 "bash, ksh93 또는 FreeBSD sh에서는 이것이 작동하지 않습니다. SIGINT는 130 종료 상태를 사망으로 처리하지 않습니다"?
Bash 매뉴얼에서:
치명적인 신호 번호 N으로 인해 명령이 종료되면 Bash는 128+N 값을 종료 상태로 사용합니다.
SIGINT의 신호 번호는 2이므로 SIGINT에서 종료되는 명령의 종료 상태는 130입니다. 그래서 제 생각에는 130번 출구를 실행하는 것은 SIGINT를 사용한 죽음과 동일하며, 130번 출구 상태는 죽음 신호로 간주됩니다.
감사해요.
답변1
$?
마지막 명령이 SIGINT로 종료된 후 표시되는 130(128+SIGINT)은 일부 쉘에 의해 발생합니다(예: bash
다른 쉘은 다른 표현을 사용합니다(예: ksh93의 256+signum, yash signum의 128+256+, / in sigint
또는 기타 텍스트). 표현).sigquit+core
rc
es
프로세스 종료 시 기본 종료 코드는 무엇입니까?더 알아보기.
프로세스는 자식을 기다리고 상태를 쿼리할 수 있습니다.
- 정지된 경우(어떤 신호를 사용할지)
- 복원된 경우
- 죽으면 (어떤 신호로)
- 만약 있다면갇힌(을 위한길d 과정)
- 넘어지면핵무기
- 시스템 호출을 통해 정상적으로 종료할지 여부
_exit()
(어떤 종료 코드를 사용할지)
이를 위해 , , , (더 이상 사용되지 않는 , 참조) 중 하나를 사용하거나 wait()
SIGCHLD waitpid()
시스템 waitid()
호출 wait3()
의 wait4()
핸들러를 사용합니다.
이러한 시스템 호출은 위의 모든 정보를 반환합니다. ( waitid()
일부 시스템을 제외하고 정상적으로 종료되는 자식 프로세스에 전달된 숫자 중 가장 낮은 8비트만 _exit()
사용할 수 있습니다.)
그러나 bash
(Bourne 및 csh와 같은 대부분의 쉘은) 모든 정보를 8자리 숫자로 묶습니다 $?
( $?
정상적으로 종료된 프로세스의 종료 코드 중 가장 낮은 8자리, 종료되거나 중단되거나 트랩된 경우 128+signum입니다. 다른 모든 정보는 사용할 수 없습니다). 분명히 일부 정보가 누락되었습니다. 특히, SIGINT로 인해 $?
프로세스가 실행되었는지, 종료되었는지 스스로 알 수 없습니다 ._exit(130)
bash
프로세스가 언제 종료되는지 명확하게 알 수 있습니다. 예를 들어 백그라운드 프로세스가 종료되면 다음이 표시됩니다.
[1]+ Interrupt sleep 20
그러나 에서는 $?
SIGINT에 의해 종료되었는지 또는 호출되었는지를 알 수 있는 충분한 정보를 제공하지 않습니다 _exit(130)
.
대부분의 쉘은 이 변환을 수행하므로 애플리케이션은 _exit(number_greater_than_127)
신호를 통해 종료를 보고하는 것 외에는 아무것도 수행하지 않습니다.
그럼에도 불구하고 프로세스가 를 실행하면 _exit(130)
이를 기다리는 프로세스는 신호에 의해 종료되는 것이 아니라 프로세스가 정상적으로 종료되었음을 감지합니다. C에서는 WIFEXITED()
다음을 반환합니다.진짜, WIFSIGNALED()
false를 반환합니다.
bash
$?
프로세스 자체는 SIGINT로 인해 프로세스가 종료되었다고 생각하지 않습니다(비록 SIGINT에 의해 종료된 것과 동일한 값을 가질 수 있다고 생각하게 하더라도 ).
따라서 이는 SIGINT 의 특수 처리를 트리거하지 않습니다 bash
. 스크립트 내에서 bash
현재 스크립트에서 실행 중인 명령은 모두 SIGINT를 수신합니다 ^C
(모두 동일한 프로세스 그룹에 있기 때문입니다).
bash
대기 중인 명령도 SIGINT에서 종료되는 경우에만 SIGINT 수신 시 종료됩니다(예를 들어 스크립트에서 vi 이하를 실행하고 ^C를 사용하여 일부 콘텐츠를 유발하거나 종료 vi
하지 않는 작업을 중단한다는 아이디어입니다. 종료 / 나중에 돌아올 less
때 스크립트는 사라지지 않습니다 ).vi
less
명령이 SIGINT 핸들러에서 실행을 bash
기다리고 있는 경우 해당 SIGINT에서 종료되지 않습니다(자식 프로세스가 중단되었다고 믿지 않기 때문에 중단되었다고 생각하지 않습니다)._exit(130)
bash
그렇기 때문에 신고하고 싶을 때SIGINT로 인해 사망, 저것핸들러에서 해당 신호를 받은 후 실제로 추가 처리를 수행하더라도 실제로는 중단됩니다., 을 수행해서는 안 되지만 _exit(130)
SIGINT로 실제로 자살해야 합니다(SIGINT에 대한 기본 핸들러를 복원한 후). 셸에서는 다음과 같습니다.
trap '
extra processing
trap - INT # restore SIGINT handler
kill -s INT "$$" # report to the parent that we have indeed been
# interrupted
' INT