화면에 stderr만 표시하고 stdout 및 stderr을 파일에 씁니다.

화면에 stderr만 표시하고 stdout 및 stderr을 파일에 씁니다.

이를 달성하기 위해 BASH 매직을 어떻게 사용할 수 있습니까?
나는 화면에서 stderr 출력을 보고 싶지만
stdout과 stderr이 모두 파일에 기록되기를 원합니다.

설명: stdout과 stderr이 동일한 파일에 들어가도록 하고 싶습니다. 발생 순서대로.
불행히도 아래 답변 중 어느 것도 이에 해당하지 않습니다.

답변1

리디렉션이 없거나 다른 것이 없더라도 >logfile 2>&1생성된 순서대로 출력이 표시된다는 보장은 없습니다.

우선, 애플리케이션의 stdout은 라인 버퍼링(tty에)되거나 버퍼링(파이프에)되지만 stderr은 버퍼링되지 않으므로 독자가 관련하는 한 출력 순서 간의 관계가 깨집니다. 구축할 수 있는 파이프라인의 후속 단계에서는 두 스트림 모두에 대해 결정론적으로 순서대로 액세스할 수 없습니다(개념적으로는 병렬로 발생하는 일이며 항상 스케줄러에 의해 제한됩니다. 독자가 슬라이스를 얻을 때까지 작성자는 두 파이프 모두에 기록했으며 어느 것이 먼저 왔는지 알 수 없습니다).

"발생 순서"는 응용 프로그램에서만 실제로 알 수 있습니다. stdout/stderr 간의 출력 순서는 잘 알려진(아마도 고전적인) 문제입니다.

답변2

구조를 사용할 때: 1>stdout.log 2>&1둘 다표준 에러그리고표준 출력이 파일로 리디렉션되기 때문에표준 출력리디렉션이 이전에 설정되었습니다.표준 에러리디렉션.

순서를 반대로 하면 얻을 수 있다.표준 출력파일로 리디렉션하고그 다음에복사표준 에러도착하다표준 출력이렇게 하면 파이프로 연결할 수 있습니다 tee.

$ cat test
#!/bin/sh
echo OUT! >&1
echo ERR! >&2

$ ./test 2>&1 1>stdout.log | tee stderr.log
ERR!

$ cat stdout.log
OUT!

$ cat stderr.log
ERR!

답변3

내 bash 스크립트 상단에 다음 줄을 추가하여 이를 달성할 수 있었습니다.

exec 1>>log 2> >(tee -a log >&2)

이것은 stdout을 file log( 1>>log)로 리디렉션한 다음 stderr을 file log( 2> >(tee -a log)로 리디렉션하고 다시 stderr() 로 리디렉션합니다 >&2). 이렇게 하면 stdout과 stderr을 순서대로 표시하는 파일을 얻게 되고 logstderr도 화면에 평소대로 표시됩니다.

문제는 파일에 추가할 때만 작동하는 것 같다는 것입니다. 연결하지 않으면 두 리디렉션이 서로 파괴되는 것처럼 보이며 마지막 출력만 얻습니다.

답변4

나는 이 정확한 요구 사항으로 인해 어려움을 겪었고 궁극적으로 간단한 해결책을 찾지 못했습니다. 내가 한 일은 다음과 같습니다.

TMPFILE=/tmp/$$.log
myCommand > $TMPFILE 2>&1
[ $? != 0 ] && cat $TMPFILE
date >> myCommand.log
cat $TMPFILE >> myCommand.log
rm -f $TMPFILE

올바른 인터리브 순서로 로그 파일에 stdout 및 stderr을 추가합니다. 오류가 발생하면(명령의 종료 상태에 따라 결정됨) 전체 출력(stdout)을 보냅니다.그리고stderr)를 stdout으로 다시 올바른 인터리브 순서로 변환합니다. 나는 이것이 내 필요에 대한 합리적인 타협이라고 생각했습니다. 증가하는 다중 실행 로그 파일 대신 단일 실행 로그 파일을 원하는 경우 다음이 더 쉽습니다.

myCommand > myCommand.log 2>&1
[ $? != 0 ] && cat myCommand.log

관련 정보