명령의 출력을 변수에 저장하고 tee를 사용하지 않고 인쇄하시겠습니까?

명령의 출력을 변수에 저장하고 tee를 사용하지 않고 인쇄하시겠습니까?

명령 출력을 변수에 저장하고 실시간으로 인쇄하는 방법을 찾으려고 합니다. 처음에는 tee작동하는 것처럼 보이는 예제를 찾았습니다 .

VARIABLE=$(./build.sh | tee /dev/tty)

그러나 문제는 가상 콘솔(예: git 허브 액션)이 있는 시스템에서 실행하면 오류가 발생한다는 것입니다 tee: /dev/tty: No such device or address. 출력을 변수에 저장하고 실시간으로 정상적으로 인쇄하는 방법을 찾고 싶습니다(예: echo, printf 등과 마찬가지로).

답변1

이것을 사용할 때의 문제점은 /dev/ttystdout이 원래 tty에 첨부되었다고 가정한다는 것입니다. 이는 반드시 GitHub Actions가 보여주는 것은 아닙니다. 이는 스크립트의 표준 출력을 다른 곳(예: 로그 파일)으로 리디렉션하는 경우에도 문제가 될 수 있습니다.

tee에 전달하려는 것은 $(...)프로세스 교체 전의 stdout(bits)입니다. 프로세스 교체는 출력을 캡처하기 위해 stdout을 사용합니다. Bash 및 기타 쉘은 사용 사례에 따라 파일 설명자를 조작할 수 있습니다.

exec 3>&1  # Open FD 3 as a duplicate of stdout (fd 1)
# Run ./build.sh but make sure it does not have FD 3 open and tee to FD 3
VARIABLE=$(./build.sh 3>&- | tee /dev/fd/3)
exec 3>&-  # Close FD 3

이렇게 하면 스크립트의 표준 출력을 스크립트 외부에서 조작(로거 또는 /dev/null 등으로 리디렉션)할 수 있으므로 WRT 표준 출력의 올바른 동작이 유지됩니다.

@SOUser가 주석에서 지적했듯이 스크립트 출력을 파일에 쓰는 데 문제가 있습니다. 문제는 tee /dev/fd/3파일을 열면 파일이 잘리고 파일에 기록된 모든 내용이 삭제된다는 것입니다. 이 문제를 해결하려고 시도하면 tee -a /dev/fd/3더 이상한 동작이 발생합니다. 어떤 이유로 캡처할 라인이 완전히 누락되었습니다.

해결책은 파일 대신 파이프에 쓰는 것이므로 ./script > test.log사용 하지 마십시오 ./script | cat > test.log. 이 방법을 사용하면 tee파일이 파일에 첨부되지 않고 잘릴 수 없는 파이프에 첨부되므로 파일을자를 수 없습니다 cat.

답변2

stderr에 제공할 수 있습니다.

VARIABLE=$(./build.sh | tee /dev/stderr)

관련 정보