1. 사용 명령어 |
(1) echo
2. 키워드 & 사용처 |
(1) 키워드
파이프, 종료 스테이터스
(2) 사용처
파이프 처리 중에 어떤 명령어 종료 스테이터스를 확인해서 명령어의 성공/실패를 판단하고 싶을 때 사용합니다.
3. 실행 예제 |
$ ./pipestatus.sh
[ERROR] sort-data.sh에 실패했습니다.
4. 스크립트 |
#!/bin/bash
# 다음과 같은 처리를 하는 경우를 가정
# script.sh : 데이터 출력
# sort-data.sh : 데이터 정렬
# calc.sh : 출력 데이터 계산
./script.sh | ./sort-data.sh | ./calc.sh > output.txt ①
# 다른 명령어를 실행하면 PIPESTATUS 값이 사라지므로 결과를 복사해둠
pipe_status=("${PIPESTATUS[@]}") ②
# 파이프 처리 중에 명령어 성공, 실패 확인
# sort-data.sh 종료 스테이터스가 0이 아닌지 확인
if [ "${pipe_status[1]}" -ne 0 ]; then ③
echo "[ERROR] sort-data.sh에 실패했습니다." >&2
fi
5. 해설 |
이 스크립트는 파이프 처리 중에 에러가 발생했는지 확인해서 에러가 발생하면 에러 메시지를 출력합니다.
여기서는 script.sh -> sort-data.sh -> calc.sh라는 세 스크립트를 순서대로 실행해서 어떤 데이터를 처리한 뒤에 그 결과를 output.txt라는 파일에 출력한다고 가정합니다. 여기서 sort-data.sh는 실패하기도 하는데 그 다음 calc.sh에서 하는 계산은 정렬이 필수가 아니므로 에러 발생 여부와 관계없이 실행 가능하다고 가정합니다. 다만 정렬에 실패하면 종료 스테이터스가 0이 아니므로 이걸 검출해서 에러 메시지만 출력하고 싶다고 합시다.
명령어 종료 스테이터스 $?를 이용하는 예제는 앞에서 많이 다루었지만 파이프 처리는 도중에 명령어 종료 스테이터스를 $?로 취득할 수 없습니다. 변수 $?는 파이프 라인 마지막에 실행된 명령어 종료 스테이터스만 대입되기 때문에 ①에서 마지막 calc.sh 종료 스테이터스만 확인할 수 있습니다.
그러나 bash 내장 변수인 PIPESTATUS를 이용하면 직접 파이프라인 처리의 모든 종료 스테이터스를 취득할 수 있습니다. PIPESTATUS는 배열 변수라서 0번에는 파이프 첫번째 종료 스테이터스가, 1번에는 파이프 두 번째 종료 스테이터스가 들어 있습니다.
서술 예 | 설명 |
${PIPESTATUS[0]} | 파이프 처리 첫 번째(script.sh) 종료 스테이터스 |
${PIPESTATUS[1]} | 파이프 처리 두 번째(sort-data.sh) 종료 스테이터스 |
${PIPESTATUS[2]} | 파이프 처리 세 번째(calc.sh) 종료 스테이터스 |
②의 ${PIPESTATUS[@]}로 사용하는 배열 첨자 @은 배열 전체를 의미합니다. 전체를 ()로 싸서 배열 전체를 셸 변수에 복사합니다.
③은 sort-data.sh 종료 스테이터스를 ${PIPESTATUS[1]}로 취득해서 TEST 명령어의 다른 값인지 확인하는 -ne 연산자로 0과 비교합니다. 종료 스테이터스가 0이 아니면 에러 메시지를 표시합니다.
이렇게 해서 파이프 처리 중에 명령어 종료 스테이터스를 취득할 수 있습니다.
6. PIPESTATUS 이용 시 주의점 |
변수 PIPESTATES를 이용할 때 주의해야 하는 것은 어떤 명령어를 실행할 때마다 변수 PIPESTATUS가 늘 변경된다는 점입니다. 예를 들어 다음은 파이프 처리하는 세 명령어 종료 스테이터스를 ECHO 명령어로 확인하는(하려고 했던) 스크립트 입니다. 하지만 이 스크립트는 잘못 작성되었습니다.
#!/bin/bash
./script.sh | ./sort-data.sh | ./calc.sh > output.txt
echo ${PIPESTATUS[0]}
echo ${PIPESTATUS[1]} A
echo ${PIPESTATUS[2]} B
이걸 실행하면 A와 B의 echo 명령어에 아무것도 표시되지 않습니다.
$ ./list2.sh
0
이것은 파이프를 사용하지 않는 명령어 처리에서도 변수 PIPESTATUS는 0개의 파이프 처리로 보고 늘 변경되기 때문입니다. 따라서 A에서는 직전의 echo 명령어의 두 번째 파이프 처리 종료 스테이터스를 얻으려고 하는데 그런 처리가 존재하지 않으므로 공백문자열을 출력합니다. B도 마찬가지입니다. 이렇듯 어떤 명령어를 실행할 때마다 PIPESTATUS는 덮어쓰기로 변경됩니다. 따라서 예제에서는 PIPESTATUS를 일단 셸 변수 pipe_status에 그대로 복사합니다.
<주의사항>
셸 변수 PIPESTATUS는 sh에는 없는 bash 고유 셸 변수 입니다. 그 외에도 몇 가지 bash 고유 셸 변수가 있는데 그 중 몇가지는 아래와 같습니다.
셸 변수명 | 의미 |
BASH | 현재 실행하고 있는 bash를 실행할 때의 전체 경로 |
DIRSTACK | 디렉터리 스택 내용(배열 변수) |
SHEELOPTS | 유효한 셸 옵션(쉼표로 구분) |
SECONDS | 셸이 실행된 초 |
HOSTNAME | 호스트명 |
UID | 셸을 실행한 사용자 ID |
GROUPS | 현재 사용자가 속한 그룹 목록(배열 변수) |
참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전
'IT 이야기 > Linux 셸 스크립트' 카테고리의 다른 글
[Linux 셸 스크립트] bash - 132 정수값으로 난수 얻기 (0) | 2021.07.13 |
---|---|
[Linux 셸 스크립트] bash - 131 간단한 메뉴를 표시해서 사용자가 선택할 수 있게 하기 (0) | 2021.07.13 |
[Linux 셸 스크립트] bash - 129 중간 파일 없이 명령어 출력을 파일처럼 다루기 (0) | 2021.07.06 |
[Linux 셸 스크립트] bash - 128 변수 내부 문자열 일부를 치환하기 (0) | 2021.07.06 |
[Linux 셸 스크립트] bash - 127 변수 내부 문자열을 n 번째부터 m 번째까지 추출하기 (0) | 2021.07.06 |
댓글