
다음을 사용하여 스크립트 내부에서 스크립트 출력을 로그 파일로 리디렉션할 수 있습니다 exec
.
#!/bin/bash
exec > stdout.log 2>&1
echo hello world
less
파일 대신 출력을 리디렉션할 수 있습니까 ? 나는 노력했다
#!/bin/bash
exec > >(less) 2>&1
# output some text
for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done
하지만 이상한 방식으로 실패합니다. 프롬프트가 덜 표시되지만 터미널에서 다시 끝납니다.
나는 이것을 스크립트의 시작 부분으로 설정하고 싶습니다(그래서 인수, tty 등에 따라 조건부일 수 있음).
답변1
스크립트가 자식 프로세스를 기다리도록 해야 합니다 less
. 그렇지 않으면 스크립트가 자식 프로세스보다 먼저 종료되고 less
갑자기 포그라운드 프로세스 그룹 외부에 있게 되어 터미널에서 명령을 읽거나 더 이상 터미널 설정을 복원할 수 없게 됩니다.
less
또한 입력이 끝날 때까지 영원히 기다리는 것을 방지하려면 스크립트에서 파이프를 닫아야 합니다.
모든 것을 종합하면:
exec > >(less) 2>&1
trap 'exec >&- 2>&-; wait' EXIT
# >&- 2>&- => close stdout and stderr => cause EOF on less' stdin
seq 1 50000
# the rest of your script
그러나 이것은 그다지 좋지 않고 대부분의 다른 쉘로 이식 가능하지 않으며 문서화되지 않은 (신뢰할 수 없는) bash 동작에 의존합니다. 스크립트에 wait
둘 이상이 있으면 제대로 작동하지 않으며 다른 백그라운드에서도 대기합니다. 로 exec > >(...)
시작된 프로세스&
더 좋은 아이디어는 무한 재귀를 피하기 위해 환경 변수를 사용하여 스크립트 자체를 호출하는 것입니다.
if [ ! "$CALLED_MYSELF" ]; then
set -o pipefail # supported in bash, but not in all the shells
CALLED_MYSELF=1 "$0" "$@" 2>&1 | less
exit
fi
seq 1 50000
# the rest of your script
답변2
다음을 시도해 보십시오(라인 없이 exec
).
for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done | less
(업데이트)
전체 스크립트를 포함하려면 다음과 같이 스크립트를 래핑할 수 있습니다.{ ... }
#!/bin/bash
{
# output some text
for (( i=1; i <= 500; i++)) do echo "hello world $i"; done
# whatever output you want...
} | less