파이프 'false'는 0이 아닌 결과 코드를 제공하지 않습니다.

파이프 'false'는 0이 아닌 결과 코드를 제공하지 않습니다.

나는 다음을 이해합니다:

true;   echo "$?"      # 0
false;  echo "$?"      # 1
true  | echo "$?"      # 0

하지만 이건 아니다:

false | echo "$?"      # 0

...왜 인쇄되지 않나요 1?

파이프라인을 강제로 실패시킨 후 복구하려면 어떻게 해야 합니까 1?

답변1

둘 다의 결과는 오해의 소지가 true | echo "$?"있습니다 false | echo "$?". 내용이 "$?"설정됩니다앞으로명령을 false명령으로 파이프하십시오 echo.

이 줄을 실행하기 위해 bash는 명령 파이프라인을 설정합니다. 파이프라인이 설정된 다음 명령이 병렬로 시작됩니다. 따라서 귀하의 예에서는 다음과 같습니다.

true;   echo "$?"      # 0
false;  echo "$?"      # 1
true  | echo "$?"      # 0

동일합니다:

true   
echo "$?"      # 0
false  
echo "$?"      # 1
echo "$?"      # 0

trueecho $?동시에 실행될 때까지는 실행되지 않습니다.

답변2

in false | echo $?, $?종료 상태가 아닙니다. false왜냐하면$?소수점까지 확장출구최근 상황관로[1] 최신이 아님주문하다,서브쉘또는하위 프로세스. 에서는 파이프가 false | echo $?아니라 false파이프의 일부일 뿐입니다. 간단한충분히명령 false;|.

set -o pipefail열려 있고 의 종료 상태가 의 false | echo $?종료 상태라고 false가정 하면 $?현재 파이프가 에코될 때 아직 종료되지 않았기 때문에 현재 파이프의 상태를 종료할 방법도 없습니다.

파이프 양쪽의 순서는 중요하지 않습니다(항상 병렬로 실행echo $?) 시작 또는 종료되거나 실제로 하위 프로세스 또는 하위 쉘에서 실행되는지 여부 .

FWIW, 서브셸에 있을 때 변수 및 기타 매개변수는언제나현재 하위 셸의 컨텍스트에서 확장: false | echo $?파이프의 각 측면에 대해 별도의 프로세스를 분기하여 수행한 경우(Bash의 경우이지만 모든 셸에서는 해당되지 않음) $?하위 프로세스에서 확장됩니다.뒤쪽에, fork()그리고 아마도 파이프의 왼쪽으로 빠져나간 후일 수도 있습니다[2].

파이프가 실패하도록 강제하고 1을 얻으려면 어떻게 해야 합니까?

를 사용하면 set -o pipefailbash, zsh 및 ksh에서 지원되며 다음에 포함되어야 합니다.향후 버전기준. 그러나 위에서 언급했듯이 이는 단지 영향을 미칩니다.$? 뒤쪽에파이프가 빠져나왔지만 파이프 자체 내부에는 없습니다.


[1]2.5.2 특수 매개변수SUSv4 표준에서. 이 경우 명령 대체가 파이프로 처리되는지 여부는 쉘에 따라 다릅니다. 대부분의 과거 및 현재 쉘에서는 :; echo `exit 13` $?인쇄되지만 13일부(예: dash, yash 또는 pdksh 파생 쉘)에서는 인쇄됩니다 0.

echo $BASHPID >&2 | echo $BASHPID >&2 | echo $BASHPID >&2[2] 변수를 이해하는 데 도움이 될 수 있는 간단한 bash 예는 다음 BASHPID과 같습니다.아니요3개의 하위 프로세스가 설정되고 실행되기 전에 확장하세요. 이와 같은 특수 매개변수는 $?이 점에서 특별하지 않습니다. 다른 변수처럼 확장됩니다.

답변3

이는 파이프라인의 두 부분이 병렬로 실행되기 때문에 false명령이 $?이미 인쇄를 시작했지만 아직 완료되지 않았으며 설정되지 않았기 때문입니다.echo$?더 일찍귀하의 경우에는 마지막 명령이 echo실행되었을 가능성이 높습니다(그리고 아마도 성공했을 수도 있습니다).

관련 정보