답변:
리턴 코드의 8 비트와 킬 (killing) 신호 수의 8 비트는 wait(2)
& co 의 리턴에서 단일 값으로 혼합됩니다 . .
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
int main() {
int status;
pid_t child = fork();
if (child <= 0)
exit(42);
waitpid(child, &status, 0);
if (WIFEXITED(status))
printf("first child exited with %u\n", WEXITSTATUS(status));
/* prints: "first child exited with 42" */
child = fork();
if (child <= 0)
kill(getpid(), SIGSEGV);
waitpid(child, &status, 0);
if (WIFSIGNALED(status))
printf("second child died with %u\n", WTERMSIG(status));
/* prints: "second child died with 11" */
}
종료 상태를 어떻게 결정합니까? 일반적으로 쉘은 8 비트 리턴 코드 만 저장하지만 프로세스가 비정상적으로 종료 된 경우 상위 비트를 설정합니다.
$ sh -c 'exit 42'; 에코 $? 42 $ sh -c 'kill -SEGV $$'; 에코 $? 세그멘테이션 오류 139 $ expr 139-128 11
이 이외의 것을 본다면, 프로그램은 아마도 정상적으로 SIGSEGV
호출 하는 시그널 핸들러를 가지고 exit
있기 때문에 실제로 시그널에 의해 죽지 않을 것입니다. (프로그램 제외하고 어느 신호를 처리하도록 선택 가능 SIGKILL
하고 SIGSTOP
).
항상 그렇듯이 Advanced Bash 스크립팅 안내서 에는 다음과 같은 유용한 정보 가 있습니다.
1 : 일반 오류에 대한 캐치
2 : 셸 내장의 오용 (Bash 문서에 따름)
126 : 호출 된 명령을 실행할 수 없음
127 : "명령을 찾을 수 없음"
128 : 종료 할 잘못된 인수
128 + n : 치명적 오류 신호 "n"
255 : 종료 상태가 범위를 벗어남 (종료시 0-255 범위의 정수 인수 만 취함)
ABSG 참조 sysexits.h
.
Linux에서 :
$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
(A whole bunch of text left out.)
#define EX_OK 0 /* successful termination */
#define EX__BASE 64 /* base value for error messages */
#define EX_USAGE 64 /* command line usage error */
#define EX_DATAERR 65 /* data format error */
#define EX_NOINPUT 66 /* cannot open input */
#define EX_NOUSER 67 /* addressee unknown */
#define EX_NOHOST 68 /* host name unknown */
#define EX_UNAVAILABLE 69 /* service unavailable */
#define EX_SOFTWARE 70 /* internal software error */
#define EX_OSERR 71 /* system error (e.g., can't fork) */
#define EX_OSFILE 72 /* critical OS file missing */
#define EX_CANTCREAT 73 /* can't create (user) output file */
#define EX_IOERR 74 /* input/output error */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#define EX_PROTOCOL 76 /* remote error in protocol */
#define EX_NOPERM 77 /* permission denied */
#define EX_CONFIG 78 /* configuration error */
#define EX__MAX 78 /* maximum listed value */
man sysexits
sysexits.h
어디에 있습니까? 모두가 참조 하는 매뉴얼 페이지 는 단지 산문입니다. 예를 들어 EX_OK
다른 코드와 마찬가지로 실제로 참조 하지만 실제로 정의하지는 않습니다. 더없는 것이 있습니까?
'1' >>> 일반적인 오류에 대한 Catchall
'2' >>> 쉘 내장의 오용 (Bash 문서에 따름)
'126' >>> 호출 한 명령을 실행할 수 없습니다
'127' >>> "명령을 찾을 수 없음"
'128' >>> 잘못된 인수가 종료되었습니다
'128 + n' >>> 치명적 오류 신호 "n"
'130' >>> 스크립트가 Control-C에 의해 종료 됨
'255' >>> 종료 상태가 범위를 벗어남
이것은 bash 용입니다. 그러나 다른 응용 프로그램의 경우 다른 종료 코드가 있습니다.
이전 답변 중 종료 상태 2를 올바르게 설명하는 것은 없습니다. 그들이 주장하는 것과는 달리 상태 2는 부적절하게 호출 될 때 명령 행 유틸리티가 실제로 리턴하는 것입니다. (예, 답은 9 살이 될 수 있으며, 수백 개의 공감대가 있으며 여전히 틀릴 수 있습니다.)
다음은 정상 종료를위한 실제적이고 장기적인 종료 상태 규칙입니다 (예 : 신호 별이 아님).
예를 들어 diff
비교하는 파일이 동일한 경우 0을, 서로 다른 경우 1을 반환합니다. 오랜 관례에 따르면, unix 프로그램 은 잘못 호출 될 때 종료 상태 2를 리턴합니다 (알 수없는 옵션, 잘못된 수의 인수 등). 예를 들어 diff -N
, grep -Y
또는 diff a b c
모두 $?
2로 설정됩니다. 1970 년대 유닉스 초기.
허용 대답은 명령이 공급되었을 때 설명 신호에 의해 종료되었습니다. 간단히 말해서, 잡히지 않은 신호로 인해 종료되면 종료 상태가 128+[<signal number>
됩니다. 예를 들어, SIGINT
( 신호 2 )에 의한 종료는 종료 상태 130을 초래한다.
몇 가지 답변은 종료 상태 2를 "bash 내장 오류 남용"으로 정의합니다. 이것은 bash (또는 bash 스크립트)가 상태 2로 종료 된 경우에만 적용됩니다 . 잘못된 사용 오류의 특수한 경우를 고려하십시오.
에서는 sysexits.h
의에 언급 된 가장 인기있는 대답은 , 종료 상태 EX_USAGE
없는 현실을 반영 ( "명령 줄 사용 오류")는 64로 정의하지만이 작업을 수행합니다 내가 인식하지 오전 어떤 잘못된 호출 수익률 64 (예 환영한다는 일반적인 유닉스 유틸리티 ). 소스 코드를 주의 깊게 읽으면 sysexits.h
실제 사용법을 반영하기보다는 열망을 나타냅니다 .
* This include file attempts to categorize possible error * exit statuses for system programs, notably delivermail * and the Berkeley network. * Error numbers begin at EX__BASE [64] to reduce the possibility of * clashing with other exit statuses that random programs may * already return.
다시 말해, 이러한 정의는 당시의 일반적인 관행을 반영하지 않지만 (1993) 의도적으로 호환되지 않았습니다. 더 안타깝습니다.
more
터미널 모드를 재설정하고 상태 0으로 종료합니다 (시도 가능).
sysexits.h 에는 표준 종료 코드 목록이 있습니다. 그것은 적어도 1993 년으로 거슬러 올라가고 Postfix와 같은 큰 프로젝트는 그것을 사용하므로 갈 길이라고 생각합니다.
OpenBSD 매뉴얼 페이지에서 :
style (9)에 따르면 프로그램을 종료 할 때 실패 조건을 나타 내기 위해 임의의 값으로 exit (3)을 호출하는 것은 좋지 않습니다. 대신 sysexits에서 사전 정의 된 종료 코드를 사용해야 프로세스의 호출자가 소스 코드를 찾지 않고도 실패 클래스에 대한 대략적인 추정을 얻을 수 있습니다.
첫 번째 근사값으로 0은 성공하고 0이 아닌 실패는 1이며 일반적인 실패는 1보다 크면 특정 실패입니다. 성공을 위해 1을 제공하도록 설계된 거짓 및 테스트의 사소한 예외 외에도 내가 발견 한 몇 가지 다른 예외가 있습니다.
보다 현실적으로 0은 성공 또는 실패를 의미하고 1은 일반적인 실패 또는 성공을 의미합니다. 2는 1과 0이 모두 성공에 사용되는 경우 일반적인 실패를 의미하지만 성공할 수도 있습니다.
diff 명령은 파일 비교가 동일하면 0을, 서로 다르면 1을, 이진이 다르면 2를 제공합니다. 2는 또한 실패를 의미합니다. less 명령은 인수를 제공하지 않으면 실패에 대해 1을 제공합니다.이 경우 실패에도 불구하고 0을 종료합니다.
실패가 권한 거부, 존재하지 않는 파일 또는 디렉토리 읽기 시도의 결과가 아닌 경우 more 명령 및 spell 명령은 실패에 대해 1을 제공합니다. 이러한 경우에는 실패하더라도 0을 종료합니다.
그런 다음 expr 명령은 출력이 빈 문자열이거나 0이 아닌 경우 성공에 1을 제공합니다.이 경우 0은 성공입니다. 2와 3은 실패입니다.
그런 다음 성공 또는 실패가 모호한 경우가 있습니다. grep이 패턴을 찾지 못하면 1을 종료하지만 실제 실패 (예 : 권한 거부)를 위해 2를 종료합니다. Klist는 티켓을 찾지 못하면 1을 종료합니다. 비록 grep이 패턴을 찾지 못하거나 빈 디렉토리 일 때보 다 더 이상 실패는 아닙니다.
불행히도 유닉스의 강력 함은 매우 일반적으로 사용되는 실행 파일에서도 논리적 규칙을 적용하지 않는 것 같습니다.
표준 Unix 종료 코드는 다른 포스터에서 언급했듯이 sysexits.h에 의해 정의됩니다. Poco와 같은 휴대용 라이브러리는 동일한 종료 코드를 사용합니다. 다음은 그 목록입니다.
http://pocoproject.org/docs/Poco.Util.Application.html#16218
신호 11은 SIGSEGV (세그먼트 위반) 신호이며 리턴 코드와 다릅니다. 이 신호는 잘못된 페이지 액세스에 대한 응답으로 커널에 의해 생성되어 프로그램이 종료됩니다. 신호 목록은 신호 매뉴얼 페이지에서 찾을 수 있습니다 ( "man signal"실행).
Linux가 0을 반환하면 성공을 의미합니다. 다른 것은 실패를 의미합니다. 각 프로그램에는 고유 한 종료 코드가 있으므로 모두 나열하는 데 시간이 오래 걸렸습니다 ...
11 오류 코드에 대해서는 실제로 세그먼테이션 오류 번호이며, 이는 대부분 프로그램이 할당되지 않은 메모리 위치에 액세스했음을 의미합니다.