내부 스크립트에서 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

관련 정보