파이프라인의 프로세스가 잘못된 종료 코드를 반환할 때까지 기다립니다.

파이프라인의 프로세스가 잘못된 종료 코드를 반환할 때까지 기다립니다.

여기에 뭔가가 빠졌나 봐요.

#!/bin/bash
timeout 5 sleep 10 &
parent_pid=$( ps --pid $! -o ppid --no-headers )
timeout_pid=$( pgrep --parent $parent_pid timeout )
wait $timeout_pid
echo "exit code: $?"

스크립트를 호출 wait-pid하고 다음을 실행합니다.

$ ./wait-pid 
exit code: 124

이것이 내가 기대하는 것입니다. 프로세스 timeout를 종료 sleep하고 124로 종료되어 wait충실하게 반환됩니다.

하지만 초기 명령에 파이프라인을 추가하면 다음과 같습니다.

timeout 5 sleep 10 | cat &
parent_pid=$( ps --pid $! -o ppid --no-headers )
timeout_pid=$( pgrep --parent $parent_pid timeout )
wait $timeout_pid
echo "exit code: $?"

이제 나는 다음을 얻습니다:

$ ./wait-pid 
exit code: 0

wait대기 중인 프로세스의 종료 코드를 여전히 반환 하면 안 됩니다 : timeout. 따라서 종료 코드가 여전히 124이면 안 됩니다.

이는 bash 4.4.20(1) 릴리스에 적용됩니다.

답변1

나는 bash 메일링 리스트에 있는 매우 박식한 Greg Wooledge로부터 답변을 받았습니다. 핵심 요소는 다음과 같습니다.

wait 명령은 "비동기 명령"이라고도 불리는 셸의 직접 하위 프로세스에서만 작동합니다. 비동기 명령이 파이프라인인 경우 원래 sh 기능 세트로 대체됩니다. 비동기 명령의 종료 상태는 파이프라인의 마지막 명령 종료 상태이며, 다른 명령의 종료 상태는 단순히 삭제됩니다.

timeout이것이 바로 파이프라인에 있을 때 종료 코드를 얻지 못하는 이유입니다 .

내가 원하는 동작을 얻는 방법은 임시 파일을 사용하여 비동기 코드 내에서 종료 코드를 캡처하는 것입니다. 다음과 같은 것 :

{
  timeout 5 sleep 10 | cat
  echo "${PIPESTATUS[@]}" > "$tempfile"
} &
wait

관련 정보