2026년 5월 27일 | 개발 깨알 상식_Tips
긴 빌드나 테스트를 돌릴 때 터미널에만 로그를 흘려보내면, 실패한 뒤에 다시 확인할 근거가 사라진다. 반대로 파일로만 리다이렉션하면 실행 중에는 어디까지 진행됐는지 보기 어렵다. 이럴 때는 tee와 process substitution을 같이 쓰면 화면 확인, 원본 로그 저장, 요약 로그 추출을 한 번에 처리할 수 있다.
문제: 로그를 보거나, 남기거나 둘 중 하나로 끝내기 쉽다
가장 흔한 형태는 표준 출력만 파일로 보내는 방식이다. 예를 들어 명령 뒤에 > build.log를 붙이면 로그는 남지만, 실행 중 터미널은 조용해진다. 실패가 빨리 나는 작업이면 괜찮지만, 10분 넘게 도는 테스트에서는 답답하다. 반대로 아무 리다이렉션 없이 화면에만 출력하면, 실패 후 위로 스크롤하다가 앞부분 로그를 놓치기 쉽다.
이때 tee는 중간 복사기처럼 동작한다. 명령 출력이 들어오면 터미널에도 보여 주고, 동시에 파일에도 쓴다. 그래서 실행 중 진행 상황을 보면서 나중에 같은 로그를 다시 열 수 있다. 기본 형태는 단순하다. some-command 2>&1 | tee run.log처럼 stderr까지 stdout으로 합친 뒤 tee로 넘기면 된다.
요약 로그를 같이 만들고 싶을 때
원본 로그만 남기는 것보다 더 편한 형태는 요약 로그를 동시에 만드는 것이다. 예를 들어 전체 테스트 로그는 run.log에 저장하고, 실패·에러·경고 줄만 run.summary.log에 따로 모으고 싶을 수 있다. 이때 process substitution을 쓴다.
some-command 2>&1 | tee run.log > >(grep -E "ERROR|FAIL|WARN" > run.summary.log)
여기서 >(...) 부분이 process substitution이다. 겉보기에는 파일처럼 보이지만, 실제로는 괄호 안 명령의 입력으로 데이터가 흘러간다. tee가 받은 로그 한 벌은 run.log로 저장되고, 다른 한 벌은 grep을 지나 요약 파일로 들어간다. 터미널에 계속 보이게 하려면 tee 출력이 어디로 가는지도 같이 생각해야 한다.
조금 더 직관적인 형태로는 tee를 두 번 쓰는 방법도 있다. 원본을 저장하면서 화면에도 보여 주고, 동시에 필터 결과를 별도 파일로 남기고 싶다면 아래처럼 나눠 쓸 수 있다.
some-command 2>&1 | tee run.log | tee >(grep -E "ERROR|FAIL|WARN" > run.summary.log)
덮어쓰기와 이어쓰기 구분하기
tee run.log는 기본적으로 파일을 덮어쓴다. 같은 파일에 여러 실행 로그를 이어 붙이고 싶으면 tee -a run.log를 쓴다. 다만 자동화에서는 무조건 이어쓰기보다 실행마다 파일명을 다르게 만드는 쪽이 안전할 때가 많다. 같은 로그 파일에 여러 실행이 섞이면 실패 원인을 다시 찾을 때 시간이 더 든다.
요약 파일도 마찬가지다. 짧은 확인 작업은 덮어쓰기가 편하고, 장기 관찰 작업은 이어쓰기가 낫다. 중요한 건 파일이 남아 있다는 사실보다, 나중에 봤을 때 어느 실행의 로그인지 알 수 있어야 한다는 점이다. 타임스탬프를 파일명에 넣거나, 첫 줄에 실행한 명령과 시작 시각을 남겨 두면 좋다.
파이프라인 종료 코드 함정
tee를 붙이면 한 가지 함정이 생긴다. 셸은 파이프라인의 마지막 명령 종료 코드를 전체 종료 코드로 보는 경우가 많다. 즉 앞의 테스트가 실패했는데 tee는 정상 종료해서, 전체 명령이 성공처럼 보일 수 있다. Bash에서는 set -o pipefail을 켜 두면 파이프라인 중간 실패를 놓칠 가능성이 줄어든다.
set -o pipefail
some-command 2>&1 | tee run.log
CI 스크립트나 자동 검증 스크립트에서는 이 차이가 꽤 중요하다. 로그는 예쁘게 남았는데 실제 실패가 성공으로 처리되면 더 위험하다. 특히 테스트 결과를 다음 단계 배포나 커밋 조건으로 쓰는 경우에는 tee를 붙인 뒤 종료 코드가 그대로 보존되는지를 꼭 확인해야 한다.
내가 쓰는 기준
- 짧은 명령: 화면 출력만으로 충분하면 tee를 붙이지 않는다.
- 긴 테스트: stderr까지 합쳐
tee run.log로 원본을 남긴다. - 반복 실패 분석: grep 요약 파일을 같이 만들어 첫 확인 시간을 줄인다.
- CI/자동화:
set -o pipefail을 켜서 실패 종료 코드를 놓치지 않는다.
tee는 화려한 도구는 아니지만, 실패를 다시 열어 보는 작업에서는 체감이 크다. 화면으로 보면서 파일에도 남기고, 필요한 줄만 별도 요약으로 빼두면 로그를 다시 찾는 시간이 줄어든다. 작은 명령 하나지만, 긴 검증을 자주 돌리는 환경에서는 관찰 가능한 실행 기록을 만드는 기본 습관에 가깝다.
'[개발 깨알 상식_Tips]' 카테고리의 다른 글
| 예전 목록에서 사라진 항목만 골라내기 (0) | 2026.06.02 |
|---|---|
| 복사 전에 바뀔 파일만 먼저 확인하기 (0) | 2026.05.29 |
| 멈춘 검증을 제한 시간 뒤 강제로 접기 (0) | 2026.05.25 |
| 공백 들어간 파일명 목록 안전하게 넘기기 (0) | 2026.05.21 |
| 큰 JSON을 통째로 열지 않고 훑어보기 (0) | 2026.05.20 |