“bash -e”를 사용할 때 서브 쉘의 출력 및 종료 값을 얻으려면 어떻게합니까? } 에 outer-scope.sh대한 호출이 inner()실패하면 종료 하려고

다음 코드를 고려하십시오

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이 아닌 종료 코드로 종료 될 수 있다는 사실을 유지하면서 함수의 출력을 얻으려면 어떻게해야합니까?



답변

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

출력 = $ (내부)

이 후에 $?는 종료 상태가 포함되며 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같은 결과를 파일.


답변

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


답변

#!/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