우분투 실전 명령어 | tee로 stdout stderr 로그 분리 저장

언제 쓰는가

배치 스크립트를 운영할 때 표준 출력과 에러 출력을 한 파일에 섞어 저장하면 원인 분석이 느려집니다. 정상 로그와 실패 로그를 분리해 두면 장애 구간을 훨씬 빨리 찾을 수 있습니다.

바로 쓰는 명령어

# 실행 결과를 stdout/stderr로 분리 저장
./deploy.sh > >(tee -a deploy.out.log) 2> >(tee -a deploy.err.log >&2)
# 타임스탬프를 붙여 에러 로그만 별도 수집
./backup.sh \
  > >(awk '{ print strftime("[%F %T]"), $0 }' | tee -a backup.out.log) \
  2> >(awk '{ print strftime("[%F %T]"), $0 }' | tee -a backup.err.log >&2)

핵심 옵션/패턴

  • > >( ... ) 는 stdout을 프로세스 치환으로 넘겨서 tee 같은 후속 처리에 연결할 때 쓴다.
  • 2> >( ... >&2) 는 stderr를 별도로 받아 파일에 저장하면서, 원래 stderr 스트림에도 유지한다.
  • tee -a 를 쓰면 기존 로그를 덮어쓰지 않고 이어서 기록한다.
  • 로그 분리 시 파일명을 *.out.log, *.err.log처럼 고정하면 운영 중 grep/집계 자동화가 쉬워진다.

명령 출력 예시

$ ./deploy.sh > >(tee -a deploy.out.log) 2> >(tee -a deploy.err.log >&2)
[INFO] build started
[INFO] image pushed
[ERROR] health check failed: timeout
[INFO] rollback completed

$ tail -n 3 deploy.out.log
[INFO] build started
[INFO] image pushed
[INFO] rollback completed

$ tail -n 3 deploy.err.log
[ERROR] health check failed: timeout

자주 하는 실수

  • 2> >(tee -a err.log) 뒤에 >&2를 빼먹으면 터미널에서 에러가 안 보여서 즉시 대응이 늦어진다.
  • tee-a를 빼고 실행해 이전 로그를 날려버리는 경우가 많다.
  • /bin/sh로 스크립트를 실행하면 프로세스 치환이 동작하지 않을 수 있다. 이 패턴은 bash 기준으로 쓴다.

검증 방법

# stderr만 고의 발생시키는 테스트
bash -c 'echo ok; echo fail >&2' > >(tee -a t.out.log) 2> >(tee -a t.err.log >&2)

# 파일 분리 확인
grep -n "ok" t.out.log
grep -n "fail" t.err.log

운영 팁

  • 크론 작업은 exec >> >(tee -a job.out.log) 2>> >(tee -a job.err.log >&2)처럼 스크립트 초반에 일괄 설정해 두면 실수 확률이 줄어든다.
  • 장애 알림은 err.log 기준으로만 트리거하고, out.log는 운영 기록으로 보관하면 노이즈를 줄일 수 있다.
  • 로그가 빠르게 커지는 작업은 logrotate와 함께 써서 디스크 압박을 예방한다.

출처

  • GNU Bash Manual
  • GNU Coreutils Manual
  • Ubuntu Manpages