출력을 다음과 같은 파일로 리디렉션했습니다.
$ ./test.bash 2> >(sed 's/^/stderr: /' >> output) > >(sed 's/^/stdout: /' >> output)
$ cat output
stdout: Hello World!
stderr: error
원래 명령의 출력을 정확하게 재현하고 싶습니다 ./test.bash
. 내가 시도한 것은 다음과 같습니다.
$ cat output | tee >(grep '^stdout: '|sed 's/^stdout: //') >(grep '^stderr: '|sed 's/^stderr: //' 1>&2) >/dev/null 2>&1 | cat
error
Hello World!
분명히 나는 출력이 올바른 순서로 이루어지기를 원합니다. 이를 수행하는 가장 좋은 방법은 무엇입니까?
답변1
현재 문서에 따라 다음이 가능할 수 있습니다.
awk '
/^stdout:/ { print substr($0, 9) }
/^stderr:/ { print substr($0, 9) > "/dev/stderr" }
' output
"녹음 스크립트"를 약간 변경하면 더욱 우아해질 수 있습니다.
답변2
당신 test.bash
이 다음과 같이 보인다면 :
echo "Hello World!"; echo error >&2
이 스크립트는 다음 loop.sh
과 같습니다.
./test.bash &> original ; echo original: ; cat original; ok=0 ; er=0
for i in {1..100}; do
rm output ; printf "(ok%d:er%d) running again: " $ok $er
./test.bash 2> >(cat >>output) > >(cat >>output) #<-EXAMINED COMMAND
if diff output original >/dev/null;
then printf "result equal...."; ((ok++))
else printf "result DIFFERENT"; ((er++)); fi
done
출력 파일이 항상 순서대로 유지된다는 것이 입증되어야 합니다.잘못된(내 테스트에서는 약 37%)
문제는 병렬 프로세스, 제어되지 않은 리디렉션 버퍼링 및 실행 속도를 방해하는 것입니다.
"expect" 패키지의 "unbuffer" 도구 솔루션을 사용하십시오(설치할 수 있는 경우). 사용:
(sleep 0.01 ; unbuffer ./test.bash)
위 스크립트의 4번째 줄에 있는 ./test.bash 대신 완벽하게 수행됩니다(오류 0%).
답변3
모든 입력 줄이 또는로 시작하는 경우 다음을 수행 stderr:
할 stdout:
수 있습니다.
perl -ne 's/^std(...):\s*//; $1 eq "err" ? print STDERR : print' output
또는 최신 버전의 bash를 사용하세요.
while read -r out line; do
[[ $out =~ ^stderr ]] && echo "$line" >&2 || echo "$line"
done < output