나는 다음을 이해합니다:
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
true
echo $?
동시에 실행될 때까지는 실행되지 않습니다.
답변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 pipefail
bash, 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
실행되었을 가능성이 높습니다(그리고 아마도 성공했을 수도 있습니다).