오류를 찾으려고 로그를 열었는데 화면이 줄줄이 지나간다. 맨 끝이 궁금했는데 cat이 친절하게 전부 보여 준 셈이다. 로그가 길 때는 읽고 싶은 위치부터 고르면 된다.
cat·less·head·tail은 언제 쓸까?
| 원하는 것 | 명령 | 보는 범위 |
|---|---|---|
| 짧은 파일 전체 | cat app.log | 모든 줄을 터미널에 출력 |
| 긴 파일을 앞뒤로 탐색 | less app.log | 화면 단위로 이동, q로 종료 |
| 시작 부분 | head -n 3 app.log | 처음 3줄 |
| 최근 부분 | tail -n 3 app.log | 마지막 3줄 |
-n 3을 생략하면 head와 tail은 기본적으로 10줄을 보여 준다. '처음 설정을 읽고 싶다'면 head, '방금 생긴 오류를 찾는다'면 tail이 출발점이다. 전체 흐름을 앞뒤로 읽어야 한다면 less가 편하다.
같은 로그에서 head와 tail의 결과는 어떻게 다를까?
예시 로그를 임시 폴더에 만든다. >는 파일을 새로 쓰므로 중요한 파일 대신 이 예제로만 시험하자.
demo_dir=$(mktemp -d)
demo_log="$demo_dir/app.log"
printf '%s\n' \
'09:00 boot' \
'09:01 ready' \
'09:02 GET /health 200' \
'09:03 GET /orders 500' \
'09:04 restart' \
'09:05 ready' \
'09:06 GET /orders 200' > "$demo_log"
head -n 3 "$demo_log"09:00 boot
09:01 ready
09:02 GET /health 200처음 3줄에는 시작과 준비 상태가 있다. 같은 파일에서 끝의 3줄을 보면 시점이 달라진다.
tail -n 3 "$demo_log"09:04 restart
09:05 ready
09:06 GET /orders 200가운데 09:03 GET /orders 500은 두 결과 어디에도 없다. head나 tail이 파일을 고친 게 아니라 보여 주는 범위만 골랐기 때문이다. 필요한 줄이 안 보인다고 로그가 사라진 것은 아니다. 전체 맥락이 필요하면 less "$demo_log"로 돌아가 읽자.
tail -f와 tail -n 0 -f는 무엇이 다를까?
tail -f "$demo_log"는 현재 파일의 마지막 줄들을 보여 준 다음, 새로 추가되는 내용을 기다린다. 실행 후 프롬프트가 돌아오지 않는 것은 멈춘 게 아니라 기다리는 중이라는 뜻이다. Ctrl+C로 종료한다.
이미 보았던 줄을 다시 보고 싶지 않다면 -n 0을 더한다. 아래 첫 줄은 2초 뒤 새 줄을 추가하도록 예약하고, 둘째 줄은 그 추가분을 기다린다.
(sleep 2; echo '09:07 GET /orders 201' >> "$demo_log") &
tail -n 0 -f "$demo_log"09:07 GET /orders 201-n 0은 '현재 줄은 0개만 보여 주고 이후 추가분부터 보자'는 뜻이다. 과거 오류를 찾는 데는 오히려 맞지 않는다. 먼저 tail -n 30이나 less로 앞뒤 맥락을 확인하자.
로그를 확인했는데 오류가 안 보이면?
먼저 파일 경로와 보는 범위를 확인한다. 다른 폴더의 app.log를 읽는다면 명령이 맞아도 답은 엉뚱하다. pwd로 현재 위치를 확인하고, 최근 3줄만 봤다면 tail -n 30처럼 범위를 넓힌다.
또 로그 한 사건이 꼭 한 줄이라고 가정하지 말자. 여러 줄로 이어지는 오류라면 마지막 한 줄만 보고 원인을 단정할 수 없다. tail -f는 새로 쓰이는 줄을 관찰하는 도구이지, 이미 지나간 모든 원인을 찾아 주는 검색기는 아니다. 로그 파일이 교체된 뒤에는 따라가던 파일과 새 파일이 다를 수 있으니, 출력이 갑자기 멎었다면 파일 경로와 갱신 상태를 다시 확인한다.
핵심 요약
cat은 전체 출력, less는 탐색, head는 처음, tail은 끝을 본다. tail -f는 뒤에 붙는 줄을 기다리고, tail -n 0 -f는 기존 줄을 빼고 새 줄부터 본다. 로그가 안 보일 때는 파일을 의심하기 전에 경로와 출력 범위를 먼저 확인하자.

