tee를 사용하여 코드 블록의 STDOUT을 블록 내에 정의된 파일 이름으로 캡처하는 방법은 무엇입니까?

tee를 사용하여 코드 블록의 STDOUT을 블록 내에 정의된 파일 이름으로 캡처하는 방법은 무엇입니까?

보내고 싶다표준 출력파일에 대한 스크립트 블록의 경우 해당 이름은 블록 내의 변수에 의해 정의됩니다. 그러나 내가 사용할 때, 블록 외부의 변수가 더 이상 존재하지 않는 것 같습니다. 아니요, 변수가 여전히 존재합니다.

스크립트:

#!/bin/bash
{
    log="mylog.txt"
    echo log: $log
} |tee $log

echo log: $log

결과:

log: mylog.txt
log:

그리고는 아니다내 로그.txt생성된 파일.

답변1

 #!/bin/bash
 log="mylog.txt"
 {
     echo log: $log
 } |tee $log

파이프는 명령 목록이 하위 쉘에서 실행되도록 합니다. 변수가 다른 서브셸에 있으므로 위쪽으로 전달할 수 없습니다. 따라서 변수를 올바르게 사용하려면 변수를 공용 컨텍스트로 이동해야 합니다.

답변2

명명된 파이프가 도움이 될 수 있습니다. 조금 더 작업하면 trap나중에 파일 시스템 정리를 처리하기 위해 설정이나 그와 유사한 작업을 거치지 않고도 강력하게 얻을 수 있습니다 . 미리 수행하기만 하면 됩니다.

pipe=/tmp/$$pipe log=mylog.txt
mkfifo "$pipe"; exec 3<>"$pipe"
{ rm "$pipe"; tee "$log"; } <&3 >/dev/tty &
pipe=$!; exec >&3 3>&-

거기. 이 순간부터 모든 스크립트의 출력은 다음 위치에 기록됩니다.(이전에)tee백그라운드 프로세스에서 읽고 있는 명명된 파이프입니다. 명명된 파이프의 특수 파일은 파일 시스템에서 제거되었으므로 나중에 정리할 필요가 없습니다. 남아 있는 유일한 참조는 스크립트의 stdoutsum 에 할당된 tee파일 설명자 입니다 stdin.

즉, 적어도 하나를 설정하는 것이 현명할 수 있습니다 trap.

trap "kill PIPE $pipe" 0

tee... 스크립트가 종료된 후 백그라운드에서 중단되지 않도록 하기 위한 것입니다 .

tee버퍼링 문제가 있는 경우( 공개 회선이 있기 때문에 문제가 되지 않을 것 같습니다 ) /dev/tty전화를 걸어 행운을 시험해 볼 수 있습니다. 이 페이지는 특히 우려되는 부분에 대한 위험을 방지합니다. 즉, 애플리케이션이 호출 후 자체 버퍼의 크기를 조정할 수 있다는 점을 언급하고 있지만 상호 작용에 대해서는 실제보다 더 긍정적입니다.teestdbufstdbufmanteeteedd

관련 정보