stdout 및 stderr을 파일에 저장하고 출력을 다시 생성합니다.

stdout 및 stderr을 파일에 저장하고 출력을 다시 생성합니다.

출력을 다음과 같은 파일로 리디렉션했습니다.

$ ./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 

관련 정보