tar 파일을 추출하고 초당 추출된 파일 수를 인쇄하는 다음 명령에 몇 가지 문제가 있습니다.
tar -xvf some_tar.tar -C a/directory | awk 'systime() > lasttime { lasttime = systime(); printf "%d files\n", NR; fflush(stdout) }'
tar 명령이 실패하더라도 awk 명령은 여전히 0을 반환하는데, 이는 tar 명령의 실패를 반영하지 않기 때문에 바람직하지 않습니다.
이 문제를 어떻게 해결할 수 있나요?
답변1
pipefail
파이프라인의 명령이 실패했는지 확인하려면 이 옵션을 설정하십시오 . Bash 외에도 ksh, zsh 및 Busybox(적어도)도 이를 지원합니다. 이 옵션이 설정되면 파이프의 종료 상태는 관련 명령에서 반환된 가장 왼쪽의 0이 아닌 종료 상태입니다.
$ set -o pipefail
$ (exit 123) | true
$ echo $?
123
또는 파이프가 조건부입니다("실패했습니다"라고 표시되어야 함).
set -o pipefail
if false | true; then
echo it succeeded
else
echo it failed
fi
답변2
최신 버전의 한 가지 접근 방식은 bash
명령 파이프라인을 호출한 후 배열 변수의 값을 확인하는 것입니다. Bash 매뉴얼 페이지에 따르면:PIPESTATUS
tar|awk
PIPESTATUS
An array variable (see Arrays below) containing a list of exit status
values from the processes in the most-recently-executed foreground
pipeline (which may contain only a single command).
따라서 tar의 종료 코드는 에 있고 ${PIPESTATUS[0]}
awk의 종료 코드는 에 있습니다 ${PIPESTATUS[1]}
.
답변3
파이프는 전혀 사용되지 않습니다. 명명된 파이프를 사용합니다.
mkfifo p
awk '...' < p &
tar -xvf some_tar.tar -C a/directory > p
echo $?
이 awk
명령은 백그라운드에서 실행되며 tar
명명된 파이프에 대한 쓰기가 시작될 때까지 차단됩니다. tar
파이프 끝을 종료하고 닫으면 끝 awk
에서 나머지 내용을 읽은 후 종료됩니다. 이 명령은 대신 종료 상태를 echo
보고합니다 .tar
awk
답변4
각 입력 라인을 호출하면 파이프라인 속도가 크게 느려질 것으로 예상되므로 systime()
파이프라인의 출력은 초당 tar 추출되는 파일 수를 정확하게 반영하지 않습니다. 진행률 표시기를 보려면 systime()
천 또는 백만 또는 일부 입력 라인마다 한 번만 호출하는 것을 고려하거나 전혀 호출하지 않고 천 또는 백만 입력 라인마다 인쇄하는 것을 고려하십시오. 초당 파일을 가져오는 중입니다 systime()
.
요청한 문제를 해결하고 호출의 오버헤드를 거의 완전히 제거하려면 다음과 같은 작업을 수행하는 것을 고려하십시오 systime()
(GNU awk를 시간 함수로 사용하고 읽은 $0
마지막 END
줄을 포함하고 입력에 NUL을 포함할 수 있음).
{ tar -xvf some_tar.tar -C a/directory && printf '\0\n'; } |
awk -v n=1000000 '
BEGIN { beg = systime() }
NR%n == 0 { printf "%d files processed\n", NR }
END {
end = systime()
if ( $0 == "\0" ) {
numFiles = NR - 1
exitStatus = 0
}
else {
numFiles = NR
exitStatus = 1
}
printf "%d files per sec\n", numFiles / (end > beg ? end - beg : 1)
exit exitStatus
}
'