흥미로운 결과가 나오면 종료 코드, 리디렉션 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 1
main case
문을 호출하면 cleanup
함수가 해당 문의 리디렉션을 상속하게 됩니다.
표준 출력에 아무것도 인쇄하지 않는 짧은 예:
cleanup () {
echo bye
}
trap cleanup EXIT
exit >/dev/null
>/dev/null
스크립트 출력을 얻으려면 삭제하세요 bye
.
결과 추적 출력은 set -x
표준 오류 스트림에 기록되고 코드는 /dev/null
해당 스트림도 리디렉션합니다. 즉, 함수 case
선언은예실행되지만 스크립트의 모든 출력을 삭제하므로 해당 출력을 볼 수 없으며 echo
추적 출력도 볼 수 없습니다.
또한 일부 다른 쉘(예: dash
및 ksh
)은 이러한 방식으로 작동하지 않습니다.
셸에서 이 문제를 해결하려면 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
쉘에 의해 할당되고 할당된 설명자는 fd
10개 이상입니다.
sh
항상 그런 것은 아니기 때문에 실행 파일을 명시적으로 호출하도록 -line bash
도 변경했습니다 .#!
bash
이것을 실행하세요:
$ ./script
+ exec
+ trap cleanup EXIT
message 1