리디렉션 및 로그 스크립트 출력

리디렉션 및 로그 스크립트 출력

다음 코드 조각을 작성하려고 합니다. 디자인 목표는 스크립트의 모든 출력을 기록하는 것이며 래퍼가 되어서는 안 됩니다. 줄이 적을수록 좋습니다.

(이 단계에서는) 사용자 입력에 관심이 없으며 대상 스크립트는 비대화형으로 실행됩니다.

이 조각에는 다음이 필요합니다.

  • 로그에 stdout을 출력하고 항상 콘솔에 에코됩니다.
  • 디버깅이 활성화된 경우 stderr을 로그로 출력하고 콘솔에 에코합니다.
  • stderr 메시지에는 타임스탬프와 기타 유용한 접두사가 있어야 합니다.

현재 최신 버전의 bash(4.2+?)에서만 테스트된 다음이 있습니다. 예를 들어 Ubuntu에서는 잘 작동하지만 CentOS6에서는 제대로 작동하지 않습니다.

DEBUG_LOG="${0##*/}.log"

# copy stdout to log always and echo to console
exec >  >(tee -a ${DEBUG_LOG})           

# copy stderr to log only, unless debugging is enabled
[ $DEBUG_TEST = "true" ] \
  && exec 2> >(tee -a ${DEBUG_LOG} >&2) \
  || exec 2>> ${DEBUG_LOG}

그래서 이거...

# Expand escaped characters, wrap at 70 chars on spaces, 
# and indent wrapped lines
msg_log() { 
  echo -e "$(date +%T) ${0##*/}: $1" \
    | fold -w70 -s | sed '2~1s/^/  /' >&2; 
}
msg_con() { 
  if [ "${DEBUG_TEST}" = "true" ]; then 
    msg_log "$1"
  else
    echo -e "$1" | fold -w70 -s | sed '2~1s/^/  /'; 
  fi
}

echo예를 들어 이러한 msg 프로시저 중 하나를 호출 할 수 있습니다 msg_con "hello world".
또한 스크립트 출력은 호출 시 설정된 환경 변수(예  DEBUG_TEST=true myscript: .

일부 셸(비지박스 등)에서는 exec가 작동하지 않을 수 있다는 내용을 읽었습니다. mkfifo와 포크 조합이 있습니다https://stackoverflow.com/a/5200754비슷한 일을 했지만 꼭 필요한 경우가 아니면 포크를 사용하지 않는 것이 좋습니다.

bash 예제를 선호하세요. 하지만 sh에서 작동하는 것이나 이식성이 더 좋은 것이 더 좋을 것입니다. 어떤 아이디어가 있나요?

답변1

function startLogging {
    exec > >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' | tee -a $logfile)
    [ ! -z "$DEBUG" ] && exec 2>&1 || exec 2> >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' >>$logfile)
    echo "=== Log started for $$ at $(date +%F-%T) ==="
}

$logfile을 뭔가로 설정해야 합니다

답변2

exec > filenamesh에서 작동해야 하며 실제로는 busybox v1.15.3(2011년 11월)에서 작동합니다. 그러나 프로세스 교체는 >(command)bash 확장이므로 이식성이 없습니다. 스크립트에서는 사용하지 마십시오. 왜 >>충분하지 않습니까?

exec 1>>${DEBUG_LOG}
exec 2>>${DEBUG_LOG}

또 다른 해결책은 스크립트 외부에서 리디렉션을 지정하는 것입니다. 스크립트가 백그라운드에서 호출될 때(cron 또는 시스템 스크립트 등을 통해) 다음과 같이 호출되어야 합니다.

./my_script 1>>${DEBUG_LOG} 2>>${DEBUG_LOG}

스크립트를 수동으로 호출하고 출력을 보려면 리디렉션하지 않고 호출하면 됩니다.

답변3

이 두 가지 예는 귀하가 언급한 내용을 달성할 것입니다

echo -n $(date) >> $DEBUG_LOG
command 2>&1 | tee -a $DEBUG_LOG

또는

echo -n $(date) >> $DEBUG_LOG
command >> $DEBUG_LOG 2>&1

답변4

tee명령이나 명령을 사용할 수 있으며 script둘 다 매우 유용합니다.

관련 정보