stdout을 건너뛰기 위한 "exec >>(tee -ia $OUT)" 옵션 생성

stdout을 건너뛰기 위한 "exec >>(tee -ia $OUT)" 옵션 생성

나는 노력한다조정다음 콘텐츠가 포함된 스크립트를 사용하세요.

# first portion of script
# ...
exec > >(tee -ia $OUT)
# ...
# second portion of script 

이 스크립트의 문제점은 stdout(내 터미널)에 많은 출력을 생성한다는 것입니다. 스크립트 작성자는 터미널 출력을 제거하는 옵션을 포함하지 않았습니다. 나는옵션을 제거 stdout하고 파일에서만 출력을 가져옵니다 $OUT.

내가 시도한 것은 다음과 같습니다.

TERM_OPT="OFF"

# first portion of script
# ...

if [ $TERM_OPT != "OFF" ]; then
     exec > >(tee -ia $OUT)
else {

# ...
# second portion of script 

} > $OUT
fi

작동하는 것 같지만 목적이 확실하지 않습니다.큰 괄호 {}이러한 맥락에서 다음과 같이그룹 명령의 GNU 부분(좋다) ;설명 목록 뒤에는 세미콜론이 필요합니다. 그러나 추가하거나 ;제거해도 아무런 차이가 없는 것 같습니다. ()중괄호 대신 괄호를 사용해야 하는지 궁금합니다 . 하지만 이렇게 하면 모든 내용이 ()하위 쉘에서 실행됩니다. 남의 대본이라 별로 마음에 안드는데&서브쉘그것이 무엇을 의미하는지 명확하지 않습니다(시도해 본 적이 없습니다).

내가 시도한 또 다른 것처럼 보인다해킹이지만 다른 사람들이 이를 사용하고 있다는 내용을 읽었으며 제대로 작동하는 것 같습니다.

TERM_OPT="OFF"

# first portion of script
# ...

if [ $TERM_OPT != "OFF" ]; then
     exec > >(tee -ia $OUT)
else
     exec > >(tee -ia $OUT 1> /dev/null)
fi

# ...
# second portion of script 

이게 더 눈에 띄어서 맘에 들어요독립적인, 그러나 이것은 고려할 가치가 없습니다.

질문은 다음과 같습니다. 이를 수행하는 올바른 방법은 무엇입니까? 즉, 올바른 방법이 무엇인지탈퇴exec > >(tee -ia $OUT)? 이러한 솔루션 중 하나가 다른 것보다 더 나은가요? 아니면 완전히 다른 작업을 수행해야 합니까?

답변1

오직$OUT일시 중지 모드에서 파일로 리디렉션하는 것이 a훨씬 쉽습니다 .

case $TERM_OPT in
  (OFF) exec >> "$OUT";;
  (*)   exec > >(tee -ia -- "$OUT")
esac

셸은 종료를 기다리지 않으므로 스크립트가 완료된 후에도 무언가가 계속 출력되는 tee것을 볼 수 있습니다 .tee

$ bash -c 'exec > >(tee -ia -- file); echo A'; echo B; sleep 1
B
A

AB 이후의 출력을 살펴보세요 .

이 문제를 해결하려면 다음을 추가할 수 있습니다.

if [ "$TERM_OPT" != OFF ]; then
  exec > /dev/null # closes the pipe to tee which should cause tee
                   # to see EOF on input and exit
  wait # waits for all asynchronous tasks including tee
fi

스크립트 끝이나 EXIT트랩에 있습니다.

또 다른 옵션(sh에서도 작동)은 전체 스크립트를 main함수에 넣고 다음을 수행하는 것입니다.

#! /bin/sh -
main() {
  # your script here
}
case $TERM_OPT in
  (OFF) main "$@" >> "$OUT";;
  (*)   main "$@" | tee -ia -- "$OUT"
esac

답변2

파일에 추가하기 위해 stdout을 리디렉션하고 터미널에 출력 복사본을 보관하지 않으려면 다음을 수행하세요.

exec >> "$OUT"

유일한 목적 tee은 하나의 스트림을 여러 스트림에 복사하는 것이므로 출력을 한 곳에 두려는 경우에는 필요하지 않습니다. 확실히 작업 할 tee -ia "$OUT" > /dev/null수도 있지만 그것은 약간 어리석은 일입니다. 다른 복사본을 버리기 위해 여전히 출력을 복사하게 됩니다.

{}이 경우 중괄호를 사용하는 것이 확실하지 않습니다.

중괄호에는 세미콜론이나 개행 문자가 필요합니다. 실제로 설명서에는 다음과 같이 나와 있습니다."목록 뒤에는 세미콜론(또는 개행)이 필요합니다."두 경우 모두 괄호가 필요하지 않습니다.

서브쉘의 의미는 서브쉘이 쉘의 독립적인 복사본에서 실행되며 서브쉘의 모든 변경 사항이 외부에서 표시되지 않는다는 것입니다. 서브쉘이 끝날 때 스크립트도 종료된다면 별 의미가 없습니다. 서브쉘이 하는 일은 원치 않는 프로세스를 시작하는 것뿐입니다.

나는 다음과 같은 것을 선택할 것입니다

if [ "$TERM_OPT" != "OFF" ]; then
     exec > >(tee -ia -- "$OUT")
else
     exec >> "$OUT"
fi

관련 정보