이전 명령이 실패할 경우 파이프라인 종료

이전 명령이 실패할 경우 파이프라인 종료

qstat -tn1스크립트 의 출력을 구문 분석하여 실행 중이거나 대기 중인 PBS 작업 수를 확인하려고 합니다 bash. 지금까지는 이것이 효과가 있었습니다:

count ()
{
    qstat -tn1 | awk '
        BEGIN { R = 0; Q = 0; }
        $10 == "R" { R++ }
        $10 == "Q" { Q++ }
        END { print R, Q }'
}

if read -r R Q < <(count)
    ...

qstat하지만 가끔 알 수 없는 이유로 실패하는 경우가 있습니다 . 이 경우에는 아무것도 인쇄하지 않고 stdout일부 오류 메시지를 인쇄하며 stderr0이 아닌 상태(상당히 표준)로 종료됩니다. 그러나 실패했다는 awk사실을 모르고 수신된 빈 입력에 대해 qstat행복하게 인쇄합니다 . 0 0그런 다음 실제로 실패했다는 사실을 모른 채 둘 read다에 0을 할당합니다 .RQqstat

  1. 실행 중인 프로세스나 대기 중인 프로세스가 없을 수 있으므로 스크립트 블록 에서 R및 0을 사용하여 초기화해야 하며 이러한 프로세스 수에 대해 빈 문자열뿐만 아니라 를 인쇄해야 합니다.QBEGINawk0
  2. 0이 아닌 상태로 종료 set -o pipefail할 수는 있지만 종료 상태를 볼 수 없으며 어쨌든 실행되어 빈 입력에 대해 인쇄하는 것을 할 수 있습니다 .countreadawk0 0
  3. 명명된 파이프와 하위 프로세스를 사용해 볼 수도 있지만 이를 관리하는 것은 너무 복잡하다고 느껴집니다.

count호출자가 실패를 감지할 수 있는 좋은 방법이 있습니까 ?

답변1

count프로세스 대체를 읽으면 반환 상태를 얻을 수 없다고 생각합니다 . 그러니 하지 마세요. 대신 결과를 변수에 저장하거나 파이프를 사용하세요.

count=$(count)
if [ $? -eq 0 ]; then
  read -r R Q <<<"$count"

또는

set -o pipefail
if count | { read -r R Q; … }

또 다른 가능성은 변수를 사용하여 PIPESTATUS첫 번째 명령의 반환 상태를 확인하는 것입니다.

count=$(qstat -tn1 | awk …)
if ((${PIPESTATUS[0]} == 0)); then
  read P Q

또는 입력이 비어 있을 때 awk가 고유한 내용(예: 아무것도 없음)을 인쇄하도록 준비합니다.

awk '
    BEGIN { R = 0; Q = 0; }
    $10 == "R" { R++ }
    $10 == "Q" { Q++ }
    END { if (NR) print R, Q }'

ifnefrom을 사용하여 명령 입력이 비어 있는지 테스트할 수 있습니다.더 많은 유틸리티또는다른 방법. 그러나 awk로 파이프를 연결하고 있으므로 이미 가지고 있는 awk 스크립트 내에서 바로 수행하는 것이 좋습니다.

명령 에서 반환 상태를 가져와야 하는 경우 qstat추가 입력 라인으로 awk에 제공할 수 있습니다. 더 쉽게 구문 분석하려면 마지막 줄을 고유한 형식으로 정렬하세요.

{
  qstat -tn1
  echo exit_code = $?
} | awk '
    /^exit_code = / { status = $3 }
    END { if (status == 0) print Q, R }
'

답변2

이것:

count ()
{
    { qstat -tn1 || echo "EPIC FAIL" } | awk '
        BEGIN { R = 0; Q = 0; }
        $10 == "R" { R++ }
        $10 == "Q" { Q++ }
        END { print R, Q }'
}

if read -r R Q < <(count)
    ...

성공 하면 qstat출력이 로 전송됩니다 awk. qstat0이 아닌 상태를 반환 하면 "EPIC FAIL"이라는 텍스트가 로 전송됩니다 awk.

이것은 단지 예일 뿐입니다. echo를 내부에서 처리할 수 있는 적절한 것으로 바꾸 awk거나 if read.

관련 정보