스크립트 내부에서 출력을 less로 리디렉션

스크립트 내부에서 출력을 less로 리디렉션

다음을 사용하여 스크립트 내부에서 스크립트 출력을 로그 파일로 리디렉션할 수 있습니다 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

관련 정보