bash 의 종료 상태 메커니즘

8714 단어 bashlinuxshell
프로그램의 종료 상태
프로그램 이 끝 날 때 부모 프로 세 스에 자신의 종료 상태 exit status 를 보고 합 니 다. int 형식의 변 수 를 전달 하여 라 이브 러 리 함수 exit 나 시스템 호출 _exit 을 통 해 현재 프로그램의 종료 상 태 를 설정 할 수 있 습 니 다. Linux 에서 WEXITSTATUS 를 통 해 돌아 오 는 종료 상태의 값 영역 은 [0, 255] 입 니 다.사이 의 정수 입 니 다. 전달 하 는 값 이 이 범위 안에 있 지 않 으 면 커 널 은 자동 으로 u_int8_t 로 강 전 됩 니 다. waitpid 라 이브 러 리 함 수 를 통 해 하위 프로 세 스 의 종료 상 태 를 얻 을 수 있 습 니 다. 그 값 은 매개 변수 wstatus 의 낮은 8 비트 에 저 장 됩 니 다.
//     wait.h  
# define WEXITSTATUS(status)    __WEXITSTATUS (status)

//     waitstatus.h  
/* If WIFEXITED(STATUS), the low-order 8 bits of the status.  */
#define    __WEXITSTATUS(status)    (((status) & 0xff00) >> 8)

다음 예 는 하위 프로 세 스 의 종료 상 태 를 어떻게 사용 하 는 지 보 여 줍 니 다 waitpid.
#include 
#include 
#include 
#include 
#include 

#define PARENT_EXIT 10086
#define CHILD_EXIT -10

int main()
{
    pid_t pid = fork();

    if (pid > 0)
    {
        int wstatus;
        //             ,   WUNTRACED            
        pid_t child_pid = waitpid(pid, &wstatus, WUNTRACED);

        if (WIFEXITED(wstatus))
            printf("Child exit status: %d
", WEXITSTATUS(wstatus)); else perror("Bad wait status
"); // exit(PARENT_EXIT); } else if (pid == 0) { // , WUNTRACED exit(CHILD_EXIT); } else { // fork perror("fork
"); exit(EXIT_FAILURE); } }

이전 예 를 컴 파일 하고 실행 하면 강 전 된 상태 코드 를 얻 을 수 있 습 니 다. 우 리 는 WIFEXITED 을 사용 하여 기다 리 는 하위 프로 세 스 가 성공 적 으로 실행 되 었 는 지 판단 한 다음 에 성공 적 인 하위 프로 세 스 WEXITSTATUS 를 실행 하여 종료 상 태 를 가 져 옵 니 다. 프로그램 에 있어 서 최종 종료 상 태 는 메 인 프로 세 스 의 종료 상태 입 니 다.
> gcc ecitcode.c;./a.out;echo "Parent exit status: $?"
Child exit status: 246  # -10     uint8
Parent exit status: 102  # 10086     uint8
POSIX 기준 에서 탈퇴 상태 0 는 이 프로그램의 정상 적 인 탈퇴 를 대표 하고 1 는 오류 가 발생 했 으 며 다른 숫자 는 프로그램 이 자체 적 으로 규정 하기 때문에 glibcstdlib.h 에서 다음 과 같은 매크로 만 정의 했다.
#define EXIT_FAILURE    1       /* Failing exit status.  */
#define EXIT_SUCCESS    0       /* Successful exit status.  */

프로그램 자 체 는 일반적으로 문서 에서 모든 종료 상태 대표 의 종료 원인 termination 을 미리 약정 합 니 다. 예 를 들 어 ls 도움말 문서 에서:
> ls --help
...    ...
Exit status:  #     
 0  if OK,  #     
 1  if minor problems  #     ,   :        
 2  if serious trouble  #     ,   :          
...    ...

명령 의 종료 상태bash 에 실 행 된 명령 의 종료 상 태 를 기록 합 니 다. $? 을 통 해 최근 실 행 된 명령 의 종료 상 태 를 얻 을 수 있 습 니 다. bash 자신의 종료 상 태 는 실 행 된 마지막 명령 의 종료 상태 이 며, 명시 적 지정 exit $? 과 같 습 니 다. 명령 을 실행 하지 않 고 종료 하면 bash 의 종료 상 태 는 0 입 니 다.bash 에서 0true 표시 하고 비 0 으로 false 표시 하 는 것 에 주의해 야 한다.
#   exit         
> bash
> exit 98
exit
> echo $?
98

#              0
> bash
exit  # Ctrl + D   
> echo $?
0

#               
> bash
> ecasd
ecasd: command not found
exit  # Ctrl + D   
> echo $?
127
bash 에서 서로 다른 종류의 명령 의 탈퇴 상태 에 대해 다음 과 같은 규정 을 한다.
내 장 된 명령: 내 장 된 명령 이 실 행 될 때 추가 하위 프로 세 스 를 시작 할 필요 가 없 기 때문에 반환 값 으로 종료 상 태 를 모 의 해 야 합 니 다. 모든 함수 가 자신의 종료 상 태 를 정의 합 니 다. 예 를 들 어 내 장 된 명령 source 은 스 크 립 트 파일 의 마지막 명령 의 반환 상 태 를 명령 의 반환 상태 로 합 니 다. bash 의 모든 내 장 된 명령 은 종료 상태 2 를 사용 합 니 다.예 를 들 어 옵션 오류, 인자 가 부족 합 니 다.
> cd -+-  #      
bash: cd: -+: invalid option
cd: usage: cd [-L|[-P [-e]] [-@]] [dir]
> echo $?
2

외부 명령: 외부 명령 의 종료 상 태 는 waitpid 받 은 하위 프로 세 스 의 종료 상 태 를 사용 하 는 것 입 니 다. 하위 프로 세 스 가 실행 과정 에서 번호 N 의 신호 로 종료 되면 종료 상 태 는 128+N 입 니 다.
Shell 함수: 정의 shell 함수 시 함수 명 은 이전에 정 의 된 읽 기 전용 함수 명 과 같 으 면 종료 상태 1 이 고 문법 오류 가 발생 하면 종료 상태 2 입 니 다. shell 함 수 를 실행 할 때 함수 에서 마지막 으로 실 행 된 명령 의 종료 상 태 는 전체 함수 의 종료 상태 입 니 다.
#           
> func () { echo; }
> readonly -f func
> func; echo $?
0
> func () { echo poi; }
bash: func: readonly function
> echo $?
1

#           
> fune () {aa}
bash: syntax error near unexpected token '{aa}'
> echo $?
2

#                     
> funr () { echo; return 6; }
> funr; echo $?
   # echo      
6  # return 6            

표현 식: ((...)) 또는 let 수식 표현 식 의 종료 상 태 는 표현 식 의 값 에 달 려 있 습 니 다. 표현 식 의 값 이 0 이면 종료 상 태 는 1 입 니 다.표현 식 의 값 이 0 이 아니라면 종료 상 태 는 0 입 니 다.
> let 0+0; echo $?
1  #       
> ((7-5)); echo $?
0  #       

명령 목록: ;, &, &&, || 로 연결 명령 을 명령 목록 이 라 고 합 니 다. 그 중에서 &&|| 로 연 결 된 명령 은 왼쪽 연결 left associativity 모드 로 목록 의 명령 을 수행 합 니 다. 전체 명령 목록 의 종료 상 태 는 마지막 명령 의 종료 상태 입 니 다. 그 밖 에 $( LISTS ) 및 절차 제어 구 조 는 다음 과 같 습 니 다.for, while 등의 반환 상태 도 구조 중의 명령 목록 의 종료 상태 입 니 다.
#   :  ping baidu.com    `baidu.com is up` ,      `baidu.com is down` 。
> ping -c1 baidu.com &> /dev/null && echo 'baidu.com is up' || echo 'baidu.com is down'
baidu.com is down
> echo $?
0  #       ping  ,                        

왼쪽 관련 모델 은 각종 언어의 논리 연산 자 최적화 에 광범 위 하 게 응용 된다. 논리 와 연산 자 에 대해&&eq1 && eq2 예 를 들 면 양쪽 만True 돌아 갑 니 다.
그래서Trueeq1 시,False 실행 되 지 않 습 니 다. 논리 나 연산 자 에 대해 서 는...eq2|| 예 를 들 면 양쪽 에 하나만 있 으 면eq1 || eq2 돌아 갑 니 다.
그래서TrueTrue 시,eq1 집행 하지 않 습 니 다.
스 크 립 트: 사용 True 또는 eq2 스 크 립 트 파일 을 실행 하 는 것 은 현재 . 에서 코드 블록 을 실행 하 는 것 과 같 습 니 다. 스 크 립 트 에서 마지막 으로 실 행 된 명령 의 종료 상 태 는 스 크 립 트 의 종료 상태 입 니 다. 사용 source 또는 bash 방식 으로 스 크 립 트 파일 을 실행 하 는 것 은 외부 명령 을 실행 하 는 것 과 같 습 니 다. 스 크 립 트 의 종료 상 태 는 외부 명령 ./ 입 니 다.의 종료 상태 입 니 다. 스 크 립 트 에서 마지막 으로 실 행 된 명령 이 bash 이면 bash 또는 exit 이 스 크 립 트 파일 을 실행 하면 실행 이 끝 난 후에 현재 . 를 종료 합 니 다.
백 스테이지 작업 과 협업 프로 세 스: 옵션 이 없 는 source 명령 을 사용 하면 마지막 으로 실 행 된 백 스테이지 작업 의 종료 상 태 를 얻 을 수 있 습 니 다. bash 를 사용 하면 지정 한 백 스테이지 작업 의 종료 상 태 를 얻 을 수 있 습 니 다. 작업 이 존재 하지 않 으 면 종료 상 태 는 wait 입 니 다. 사용 wait -n 127 에 있 습 니 다.에서 실 행 된 명령 의 종료 상 태 는 백 스테이지 작업 과 마찬가지 로 coproc 가 져 올 수 있 습 니 다. sub shell 자신의 종료 상 태 는 항상 wait 입 니 다.
> { sleep 10; aad; } &
[1] 558
> wait -n 1
[1]+  Exit 127                { sleep 10; aad; }

> coproc { sleep 10; aad; }
[1] 558
> echo $?
0  #    coproc      
> jobs
[1]+  Exit 127                coproc COPROC { sleep 10; aad; }

파이프 명령: 기본적으로 파이프 의 종료 상 태 는 파이프 의 마지막 명령 의 종료 상태 에 달 려 있 습 니 다. coproc 설정 되 어 있 으 면 파이프 의 모든 명령 의 종료 상태 가 0 일 때 만 전체 파이프 의 종료 상태 가 set -o pipefail 이 고 그렇지 않 으 면 마지막 0 이 아 닌 종료 상태 입 니 다. 파이프 앞 에 추가 0기 호 는 전체 파이프 의 종료 상태 에 대해 반대 할 수 있 습 니 다. 0 중의 특수 변수 ! 는 최근 에 실 행 된 프론트 파이프 의 종료 상 태 를 배열 로 저장 할 수 있 습 니 다. 주의해 야 할 것 은 하나의 명령 도 기록 되 는 것 입 니 다. 즉, bash$PIPESTATUS 은 등가 입 니 다.
#                    
> ps | xxp 2>/dev/null | cat; echo $?
0
> set -o pipefail 
> ps | xxp 2>/dev/null | cat; echo $?
127  #     pipefail               

#                       
> easd 2>/dev/null | ls /nou 2>/dev/null | more 2>/dev/null
> echo ${PIPESTATUS[@]}
127 2 0

#                 
> ping asbasdasd 2>/dev/null; echo ${PIPESTATUS[0]}
2
> ping asbasdasd 2>/dev/null; echo $?
2

참고 자료
  • Exit status range
  • Bash man page
  • 좋은 웹페이지 즐겨찾기