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작동하지만 스크립트가 실행되는 방식에 액세스할 수 없습니다. CICD 시스템입니다. exec를 사용하여 스크립트 내부에서 "결합된 출력"을 수행할 수 있어야 합니다.

CI/CD 라이브러리를 만들고 있는데 클라이언트가 라이브러리를 어떤 용도로 사용할지 알 수 없으므로 각 사용 사례를 설명하고 싶습니다.

답변1

접근 방식을 간단히 확장하면 다음과 같습니다.

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

표준 오류는 이름이 지정된 파일에 기록되고 stderr표준 stdout출력은 콘솔(또는 exec실행 시 두 파일 설명자가 가리키는 모든 항목) 및 에 기록됩니다 stdall. (추가)는 쓰기를 시작한 두 번째 항목이 덮어쓰이는 것을
tee -a방지하는 데 필요합니다 .stdalltee

참고하세요순서리디렉션이 수행되는 것은 관련이 있습니다. 두 번째 프로세스 대체는 첫 번째 리디렉션의 영향을 받습니다. 즉, 발생한 오류는 로 전송됩니다 >(tee -a stderr stdall). 물론 /dev/null이러한 부작용을 피하기 위해 두 번째 프로세스 대체의 표준 오류를 로 리디렉션할 수 있습니다. 표준 오류 이전에 표준 출력을 리디렉션하면 모든 오류가 stdoutstdall에도 전송됩니다.

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

답변2

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

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를 제공하고 애플리케이션이 메시지로 수행할 작업을 결정해야 합니다.

관련 정보