[shell] 스크립트 자체 내에서 전체 셸 스크립트의 출력을 어떻게 리디렉션합니까?

Bourne 쉘 스크립트의 모든 출력을 어딘가로 리디렉션 할 수 있습니까?하지만 스크립트 자체 내에 쉘 명령이 있습니까?

단일 명령의 출력을 리디렉션하는 것은 쉽지만 다음과 같은 것을 원합니다.

#!/bin/sh
if [ ! -t 0 ]; then
    # redirect all of my output to a file here
fi

# rest of script...

의미 : 스크립트가 비 대화식으로 실행되는 경우 (예 : cron) 모든 파일의 출력을 파일로 저장하십시오. 쉘에서 대화식으로 실행하는 경우 평소와 같이 출력이 stdout으로 이동하십시오.

FreeBSD 주기적 유틸리티가 일반적으로 실행하는 스크립트에 대해이 작업을 수행하려고합니다. 매일 실행되는 이메일의 일부로 매일 보지 않아도되므로 발송하지 않습니다. 그러나이 하나의 특정 스크립트 내에서 무언가 실패하면 나에게 중요하며 일상적인 작업 의이 부분의 출력을 캡처하고 이메일로 보내려고합니다.

업데이트 : Joshua의 대답은 현장에 있지만, 전체 스크립트 주위에 stdout 및 stderr을 저장하고 복원하고 싶었습니다.

# save stdout and stderr to file descriptors 3 and 4, then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1

# ...

# restore stdout and stderr
exec 1>&3 2>&4



답변

업데이트 된 질문을 해결합니다.

#...part of script without redirection...

{
    #...part of script with redirection...
} > file1 2>file2 # ...and others as appropriate...

#...residue of script without redirection...

중괄호 ‘{…}’는 I / O 리디렉션 단위를 제공합니다. 중괄호는 명령이 나타날 수있는 위치 즉, 줄의 시작 부분이나 세미콜론 뒤에 나타납니다. ( 예, 더 정확하게 만들 수 있습니다. 떨고 싶다면 알려주세요. )

표시된 리디렉션으로 원래 stdout 및 stderr을 보존 할 수는 있지만, 나중에 스크립트를 유지 관리해야하는 사람들이 위에 표시된대로 리디렉션 된 코드의 범위를 지정하면 진행 상황을 이해하는 것이 더 간단합니다.

Bash 매뉴얼의 관련 섹션은 그룹화 명령I / O 리디렉션 입니다. POSIX 쉘 스펙의 관련 섹션은 복합 명령I / O 리디렉션 입니다. Bash에는 몇 가지 추가 표기법이 있지만 POSIX 셸 사양과 비슷합니다.


답변

일반적으로이 중 하나를 스크립트 상단 또는 상단에 배치합니다. 명령 줄을 구문 분석하는 스크립트는 구문 분석 후 리디렉션을 수행합니다.

stdout을 파일로 보내기

exec > file

stderr와 함께

exec > file
exec 2>&1

stdout과 stderr을 파일에 추가하십시오.

exec >> file
exec 2>&1

조나단 레플러는 그의 주석에서 언급 한 :

exec두 개의 별도 작업이 있습니다. 첫 번째는 현재 실행중인 쉘 (스크립트)을 새로운 프로그램으로 교체하는 것입니다. 다른 하나는 현재 셸에서 I / O 리디렉션을 변경하는 것입니다. 에 대한 인수가 없어서 구별됩니다 exec.


답변

전체 스크립트를 다음과 같은 함수로 만들 수 있습니다.

main_function() {
  do_things_here
}

그런 다음 스크립트 끝에 다음이 있습니다.

if [ -z $TERM ]; then
  # if not run via terminal, log everything into a log file
  main_function 2>&1 >> /var/log/my_uber_script.log
else
  # run via terminal, only output to screen
  main_function
fi

또는 각 실행마다 모든 것을 로그 파일에 기록하고 간단하게 다음을 수행하여 stdout에 출력 할 수 있습니다.

# log everything, but also output to stdout
main_function 2>&1 | tee -a /var/log/my_uber_script.log


답변

원래 stdout 및 stderr을 저장하려면 다음을 사용할 수 있습니다.

exec [fd number]<&1
exec [fd number]<&2

예를 들어 다음 코드는 “walla1″및 “walla2″를 로그 파일 ( a.txt)로, “walla3″을 stdout으로, “walla4″를 stderr로 인쇄합니다.

#!/bin/bash

exec 5<&1
exec 6<&2

exec 1> ~/a.txt 2>&1

echo "walla1"
echo "walla2" >&2
echo "walla3" >&5
echo "walla4" >&6


답변

[ -t <&0 ] || exec >> test.log


답변