쉘 스크립트의 경우와 같이 stdout을 파일로, stderr을 파일로, stdout+stderr을 파일로, stdout+stderr을 터미널에 저장하는 방법

쉘 스크립트의 경우와 같이 stdout을 파일로, stderr을 파일로, stdout+stderr을 파일로, stdout+stderr을 터미널에 저장하는 방법

쉘 스크립트처럼 stdout을 한 파일에, stderr를 다른 파일에, stdout+stderr을 세 번째 파일에, stdout+stderr을 터미널에 저장하려면 어떻게 해야 합니까?

나는 이것을 다른 곳에서 찾았습니다.

exec > >(tee std_out) 2> >(tee err_out >&2)
ls # Should got to std_out
fsdfs # Command not found goes to err_out

정말 가깝습니다. 실행하면 bash test.sh 2>&1 | tee output작동하지만 스크립트가 실행되는 방식에 액세스할 수 없습니다. 이것은 CID 시스템입니다. exec를 사용하여 스크립트 내부에서 "결합된 출력"을 수행할 수 있어야 합니다.

CI/CD 라이브러리를 만들고 있지만 고객이 라이브러리를 어떤 용도로 사용할지 알 수 없으므로 모든 사용 사례를 고려하고 싶습니다.

답변1

간단하게 방법을 확장하세요.

exec 2> >(tee -a stderr stdall) 1> >(tee -a stdout stdall)

stderr은 stdout이라는 파일에 기록되고 stderr, stderr stdout및 stdout은 콘솔(또는 exec런타임 시 두 파일 설명자가 가리키는 모든 항목) 및 stdout에도 기록됩니다 stdall. (추가)는 쓰기 시작하는 두 번째 데이터에 의해 덮어쓰이는 것을
tee -a방지하기 위해 필요합니다 .stdalltee

알아채다주문하다리디렉션을 수행하는 것이 관련됩니다. 두 번째 프로세스 교체는 첫 번째 리디렉션의 영향을 받습니다. 즉, 발생하는 오류는 으로 전송됩니다 >(tee -a stderr stdall). 물론 /dev/null이러한 부작용을 피하기 위해 두 번째 프로세스 교체의 표준 오류를 리디렉션할 수 있습니다. 표준 오류 이전에 표준 출력을 리디렉션하면 모든 오류가 stdout및 로 전송됩니다 stdall.

Bash 프로세스 교체 명령이 실행되므로비동기적으로, 생성된 순서대로 출력이 표시된다는 보장은 없습니다. 더 나쁜 것은 표준 출력과 표준 오류의 조각이 같은 줄에 나타날 수 있다는 것입니다.

답변2

$0> >(...)변덕스럽고 신뢰할 수 없는 bash의 구성 에 의존하는 대신 스크립트가 스스로 실행될 수 있습니다(무한 재귀를 피하기 위해 환경 변수를 설정하고 확인하여) .

if [ "$REDIRECTED" != 1 ]; then
        export REDIRECTED=1
        set -o pipefail
        { { "$0" | tee stdout >&3; } 2>&1 | tee stderr; } 3>&1 | tee stdboth
        exit
fi
# rest of your script here

라인 버퍼링은 사용되지 않으므로 tee(강제로 그렇게 할 수 없음 stdbuf(1)) stdout 및 stderr에 기록된 데이터 순서는 최종 출력에서 ​​고려되지 않습니다. 전체 버퍼링을 사용하고 stdout과 stderr 모두에 쓰는 명령의 경우 라인 버퍼링도 tee도움이 되지 않으며, 더 나쁜 경우 stdout의 절반과 stderr의 절반인 출력 라인으로 끝날 수도 있습니다.

나는 이 문제가 쉘 언어와 미리 만들어진 명령줄 유틸리티만으로는 해결될 수 없다고 생각합니다.

답변3

CI/CD 라이브러리를 만들고 있지만 고객이 라이브러리를 어떤 용도로 사용할지 알 수 없으므로 모든 사용 사례를 고려하고 싶습니다.

이러한 상황을 고려하면 bash가 출력을 처리해야 하는지 의문이 듭니다. 이 경우 이상적으로는 출력에 타임스탬프를 찍고 표준 출력 유형의 ID를 제공하면 애플리케이션이 메시지로 무엇을 할지 결정해야 합니다.

관련 정보