"bash -e"를 사용할 때 서브 쉘의 출력 및 종료 값을 얻으려면 어떻게합니까?


70

다음 코드를 고려하십시오

outer-scope.sh

#!/bin/bash
set -e
source inner-scope.sh
echo $(inner)
echo "I thought I would've died :("

inner-scope.sh

#!/bin/bash
function inner() { echo "winner"; return 1; }

outer-scope.sh대한 호출이 inner()실패하면 종료 하려고 합니다. $()서브 쉘을 호출하기 때문에 이런 일이 발생하지 않습니다.

함수가 0이 아닌 종료 코드로 종료 될 수 있다는 사실을 유지하면서 함수의 출력을 얻으려면 어떻게해야합니까?

답변:


102

$()종료 상태를 유지합니다. 할당과 같이 자체 상태가없는 명령문에 사용하면됩니다.

출력 = $ (내부)

이 후에 $?는 종료 상태가 포함되며 inner모든 종류의 검사를 사용할 수 있습니다.

output=$(inner) || exit $?
echo $output

또는:

if ! output=$(inner); then
    exit $?
fi
echo $output

또는:

if output=$(inner); then
    echo $output
else
    exit $?
fi

(참고 : exit인자가없는 베어 exit $?는 마지막 명령의 종료 상태로 종료됩니다. 두 번째 형식은 명확성을 위해서만 사용했습니다.)


또한 레코드의 경우 : source이 경우 완전히 관련이 없습니다. 당신은 정의 할 수 있습니다 inner()에서 outer-scope.sh같은 결과를 파일.


왜 그래도 $인데? 스크립트가 자동으로 종료되지 않는 $ ()의 종료 상태를 포함합니다 (-e가 설정되어있는 경우)? 편집 : 당신이 내 질문에 대답했다고 생각하지 않습니다, 감사합니다!
jabalsad

잘 모르겠습니다. (위의 어떤 것도 테스트하지 않았습니다.) 그러나 -e에 대한 제한이 있습니다. 모두 bash의 맨 페이지에 설명되어 있습니다. 또한에 대해 질문하는 echo $()경우 echo명령 줄 에 종료 코드 (일반적으로 0)가있는 경우 서브 쉘의 종료 코드가 무시되기 때문일 수 있습니다 .
grawity

1
흠, 내가 입력 if ! $(exit 1) ; then echo $?; fi하면 얻을 수 0있습니다. if종료 값을 유지해야하는 경우 확실하지 않습니다 .
Ron Burk

@ grawity-Dash와 함께 작동합니까? 성가신 Autoconf 동작 (Sun 또는 IBM의 컴파일러 가 터미널에 잘못된 옵션 을 인쇄 할 때 Autoconf보고 성공)을 해결하려고합니다 .
jww

3
if ! output=$(inner); then exit $?; fi$?의 리턴 코드 !대신의 리턴 코드를 제공하므로 리턴 코드 0으로 종료됩니다 inner. 당신은 원하는 행동을 얻을 수 if output=$(inner); then : ; else exit $?; fi있지만 분명히 더 장황하다
SJL

26

BashFAQ / 002 참조 :

둘 다 원하는 경우 (출력 및 종료 상태) :

output=$(command)
status=$? 

특별한 경우

함수 로컬 변수가있는 까다로운 경우에 대해 다음 코드를 비교하십시오.

f() { local    v=$(echo data; false); echo output:$v, status:$?; }
g() { local v; v=$(echo data; false); echo output:$v, status:$?; }

우리는 얻을 것이다 :

$ f     # fooled by 'local' with inline initialization
output:data, status:0

$ g     # a good one
output:data, status:1

왜?

서브 쉘의 출력이 local변수 를 초기화하는 데 사용될 때, 종료 상태는 더 이상 서브 쉘이 아니라 명령 일 가능성이 높습니다 .local 0

참조 https://stackoverflow.com/a/4421282/537554


3
이것이 실제로 질문에 대답하지는 않았지만 오늘 나에게 유용했습니다. +1.
fourpastmidnight

1
bash 명령의 종료 상태는 항상 마지막으로 실행 된 명령의 종료 상태입니다. 강력한 형식의 언어로 너무 많은 시간을 보내면 "local"이 형식 지정자가 아니라 또 다른 명령이라는 것을 잊어 버리기 쉽습니다. 이 점을 다시 말씀해 주셔서 감사합니다. 오늘 도움이되었습니다.
markeissler

2
와우, 나는 지금이 정확한 문제에 부딪 쳤고 당신은 그것을 정리했습니다. 감사!
krb686

4
#!/bin/bash
set -e
source inner-scope.sh
foo=$(inner)
echo $foo
echo "I thought I would've died :("

을 추가 echo하면 서브 쉘이 독립형이 아니고 (별도로 점검되지 않음) 중단되지 않습니다. 할당은이 문제를 우회합니다.

이 작업을 수행하고 출력을 파일로 리디렉션하여 나중에 처리 할 수도 있습니다.

tmpfile=$( mktemp )
inner > $tmpfile
cat $tmpfile
rm $tmpfile

물론, $ tmpfile은 두 번째 변종에 계속 존재합니다.
Daniel Beck
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.