Bash 리디렉션 이상한 동작

Bash 리디렉션 이상한 동작

흥미로운 결과가 나오면 종료 코드, 리디렉션 stdout및 사례 설명을 캡처하느라 바쁘고 stderr누군가 이에 대해 밝혀줄 수 있기를 바랍니다.

나는 bash 5.1.16을 사용하고 있습니다.

이 블록은 내가 보고 있는 동작을 복제하는 데 사용될 수 있습니다.

#!/bin/sh -x

cleanup () {
    case $? in
        1) echo "message 1" ;;
        9) echo "message 2" ;;
    esac
}

trap cleanup EXIT

case 0 in
    0) exit 1 ;;
    2) echo "yay" ;;
esac > /dev/null 2>&1

xtrace 출력 > /dev/null 2>&1:

+ trap cleanup EXIT

다음이 없는 xtrace 출력 > /dev/null 2>&1:

+ trap cleanup EXIT
+ case 0 in
+ exit 1
+ cleanup
+ case $? in
+ echo 'message 1'
message 1

여기서 무슨 일이 일어나고 있는 걸까요? 리디렉션으로 인해 Case 문이 전혀 실행되지 않는 이유는 무엇입니까?

답변1

트랩은 EXIT호출될 때 리디렉션을 통해 수행됩니다. 코드에서 exit 1main case문을 호출하면 cleanup함수가 해당 문의 리디렉션을 상속하게 됩니다.

표준 출력에 아무것도 인쇄하지 않는 짧은 예:

cleanup () {
        echo bye
}

trap cleanup EXIT

exit >/dev/null

>/dev/null스크립트 출력을 얻으려면 삭제하세요 bye.

결과 추적 출력은 set -x표준 오류 스트림에 기록되고 코드는 /dev/null해당 스트림도 리디렉션합니다. 즉, 함수 case선언은실행되지만 스크립트의 모든 출력을 삭제하므로 해당 출력을 볼 수 없으며 echo추적 출력도 볼 수 없습니다.

또한 일부 다른 쉘(예: dashksh)은 이러한 방식으로 작동하지 않습니다.

셸에서 이 문제를 해결하려면 bash스크립트 시작 부분에 표준 오류 파일 설명자를 복사하여 함수에서 명시적으로 사용할 수 있습니다 cleanup. 나는 이것이 다음에 사용될 것이라고 가정하기 때문에 표준 오류 스트림을 사용하고 있습니다.진단정보.

귀하의 코드와 추가 사항:

#!/bin/bash -x

exec {fd}>&2

cleanup () {
    case $? in
        1) echo "message 1" ;;
        9) echo "message 2" ;;
    esac >&$fd
}

trap cleanup EXIT

case 0 in
    0) exit 1 ;;
    2) echo "yay" ;;
esac > /dev/null 2>&1

쉘에 의해 할당되고 할당된 설명자는 fd10개 이상입니다.

sh항상 그런 것은 아니기 때문에 실행 파일을 명시적으로 호출하도록 -line bash도 변경했습니다 .#!bash

이것을 실행하세요:

$ ./script
+ exec
+ trap cleanup EXIT
message 1

관련 정보