명령의 종료 상태는 명령에 의해 구현됩니까, 아니면 명령을 실행하는 쉘 프로세스에 의해 구현됩니까?

명령의 종료 상태는 명령에 의해 구현됩니까, 아니면 명령을 실행하는 쉘 프로세스에 의해 구현됩니까?

배쉬 매뉴얼에서

실행된 명령의 종료 상태waitpid시스템 호출이나 동등한 함수에 의해 반환된 값입니다. 종료 상태의 범위는 0부터 255까지인데, 쉘에서는 아래 설명처럼 구체적으로 125보다 높은 값을 사용할 수도 있습니다. 쉘 내장 및 복합 명령의 종료 상태도 이 범위로 제한됩니다. 어떤 경우에는 쉘이 특정 오류 모드를 나타 내기 위해 특수 값을 사용합니다.

  1. 실행된 명령의 종료 상태를 결정하는 것은 무엇입니까?

    • 명령 자체, 즉 명령의 구현이 종료 상태를 결정하는지 여부, 즉 명령 실행을 위한 명령줄 인수를 구문 분석하는 것이 명령에 내재된 것처럼 실행된 명령의 종료 상태를 결정하는 것이 명령의 고유 속성인지 여부
    • 이 명령을 실행하는 쉘 프로세스는 무엇입니까? 위에서 언급한
      시스템 호출 waitpid은 실행된 명령의 종료 상태가 쉘 프로세스에 의해 구현되고 명령 자체는 자체 실행의 종료 상태와 아무 관련이 없는 것으로 보입니다.
  2. Bash 프로세스에서 실행된 명령의 종료 상태를 언제 얻을 수 있습니까?

    • bash 프로세스가 대화형인 경우에만, 또는
    • bash 프로세스가 대화형인지 비대화형인지에 관계없이? bash 프로세스가 비대화형일 때 bash 프로세스에서 실행된 명령의 종료 상태를 어떻게 검색합니까?

답변1

명령 자체는 exit()시스템 호출에 대한 인수를 통해 종료 상태를 제공할 수 있습니다. 쉘(또는 다른 프로그램, Perl이나 PHP는 어떻습니까?)은 system()또는 시스템 호출을 통해 하위 프로세스의 종료 상태를 얻을 수 있습니다. 자식 프로세스의 상태가 변경되면 Unix/Linux/*BSD 커널은 SIGCHLD를 부모 프로세스에 전달하도록 준비합니다.wait()waitpid()

그러나 다른 상황도 있습니다. SIGKILL을 통해 종료된 프로세스는 종료될 기회가 없습니다. 잘못된 주소를 역참조하는 프로세스는 exit()SIGSEGV 신호 처리기가 설치되어 있지 않으면 호출할 수 없습니다 . 이러한 경우 커널은 "신호에 의해 종료됨"을 나타내는 비트와 프로세스 종료를 유발한 신호를 포함하는 종료 상태를 계산합니다. 커널이 계산한 종료 상태는 종료된 프로세스의 상위 프로세스로 전달됩니다.

답변2

이 코드는 종료 상태를 설정합니다.

$ perl -e 'END { $? = 42 }'; echo $?
42
$ 

그렇지 않다면

$ perl -e 'sleep 999; END { $? = 42 }'
^C
$ echo $?
130
$ echo $((130-128))
2
$ kill -l | head -2
 1    HUP Hangup                        17   STOP Stopped (signal)         
 2    INT Interrupt                     18   TSTP Stopped
$ 

아니면 실제로

$ perl -e '$SIG{INT}=sub{exit 7};sleep 999'                   
^C$ echo $?
7
$ 

아니면 누군가를 기분 좋게 만들어서는 안됩니다 SIGKILL.

그렇지 않으면 bash설명서가 waitpid16비트 상태어를 설정했지만 bash쉘 변수에 해당 상태어의 하위 집합만 전달하기 때문에 오해의 소지가 있습니다 $?. 이는 쉘 사용자가 결과를 8비트 값(그렇지 않음)으로 처리하려고 시도하는 경우 waitpid무지와 혼란을 초래할 수 있습니다 .

$ false; echo $?
1
$ perl -E 'system("false"); say $?'
256
$ perl -E 'system("false"); say $? >> 8'
1
$ 

답변3

프로세스는 자체 종료 코드를 결정합니다. 종료되면 종료 코드를 제공하고, 아무것도 제공되지 않은 경우 0(오류 없음)으로 가정합니다.

대화형 및 비대화형 쉘 모두에서 이전 명령의 종료 코드는 값을 통해 얻을 수 있습니다 $?.

관련 정보