리눅스 tail 명령어 사용법 - 로그 실시간 확인과 -f, -F 차이
이 명령어를 언제 쓰는가
서비스를 재시작하고 나서 정상적으로 떴는지 확인할 때, 배포 직후 에러가 터지는지 지켜볼 때 쓰는 명령이다. 로그는 항상 끝에 쌓이므로 실무에서 로그를 볼 때는 head 보다 tail 을 훨씬 많이 친다.
특히 tail -f 는 파일이 커지는 것을 실시간으로 따라간다. 배포 창을 하나 띄워 두고 로그가 흐르는 것을 보면서 작업하는 것이 기본 패턴이다.
기본 형식
tail [옵션] 파일...
옵션 없이 쓰면 마지막 10줄을 출력한다. 파일 여러 개를 주면 ==> 파일명 <== 헤더와 함께 각각의 끝부분을 보여준다.
자주 쓰는 옵션
| 옵션 | 의미 | 예시 |
|---|---|---|
-n N | 마지막 N줄을 출력한다 | tail -n 100 app.log |
-n +N | N번째 줄부터 끝까지 출력한다 | tail -n +2 data.csv |
-f | 파일이 커지는 것을 계속 따라간다 | tail -f app.log |
-F | 파일이 지워지거나 새로 만들어져도 다시 붙잡는다 | tail -F /var/log/nginx/error.log |
-c N | 줄이 아니라 마지막 N바이트를 출력한다 | tail -c 200 dump.bin |
--pid=PID | 해당 프로세스가 끝나면 tail 도 자동 종료한다 (GNU) | tail -f out.log --pid=$! |
실전 예제
1) 배포 직후 애플리케이션 로그를 실시간으로 지켜본다. 가장 많이 치는 형태다.
tail -f /var/log/app/app.log
종료는 Ctrl-C 다.
2) 로그가 매일 로테이션되는 환경에서 끊기지 않게 따라간다. logrotate 가 도는 서버에서는 -f 대신 항상 -F 를 쓴다.
tail -F /var/log/nginx/access.log
3) 여러 로그를 한 화면에서 동시에 본다. 웹 서버와 애플리케이션 로그를 나란히 놓고 원인을 대조할 때 쓴다.
tail -F /var/log/nginx/error.log /var/log/app/error.log
새 줄이 들어올 때마다 어느 파일에서 왔는지 헤더가 다시 찍힌다.
4) 실시간 로그에서 특정 문자열만 걸러 본다. 트래픽이 많은 서버에서 관심 있는 줄만 보는 방법이다.
tail -F app.log | grep --line-buffered 'ERROR'
5) CSV의 헤더 행을 빼고 데이터만 넘긴다. 집계 파이프라인 앞단에서 자주 쓴다.
tail -n +2 users.csv | awk -F, '{print $3}' | sort | uniq -c
6) 최근 로그 200줄을 파일로 떠서 공유한다. 티켓에 첨부할 때 전체 로그를 보내지 않아도 된다.
tail -n 200 /var/log/app/error.log > /tmp/error-tail.txt
함정과 주의점
-f 는 로그 로테이션이 일어나면 조용히 멈춘다. 이것이 실무에서 가장 자주 데는 지점이다. -f 는 파일명이 아니라 열어 둔 파일(inode) 을 따라간다. logrotate 가 access.log 를 access.log.1 로 옮기고 새 access.log 를 만들면, tail 은 이름이 바뀐 옛날 파일을 계속 보고 있게 된다. 화면에는 아무 오류도 안 뜨고 그냥 로그가 안 흐를 뿐이라 "트래픽이 끊겼나" 하고 오판하기 쉽다. -F 는 파일명을 기준으로 다시 열기 때문에 이 문제가 없다. 로그를 볼 때는 그냥 항상 -F 를 쓴다고 외워도 무방하다.
tail -f | grep 결과가 한참 뒤에 몰려서 나온다. grep 은 출력 대상이 터미널이 아니라 파이프면 4KB 단위로 버퍼링한다. 그래서 조건에 맞는 줄이 생겨도 버퍼가 찰 때까지 화면에 안 나온다. GNU grep 은 --line-buffered, sed 는 -u, awk 는 fflush() 로 해결한다.
-n 2 와 -n +2 는 완전히 다른 명령이다. 앞은 "마지막 2줄", 뒤는 "2번째 줄부터 끝까지"다. 플러스 하나 빠뜨려서 데이터 대부분을 날리는 실수가 흔하다.
백그라운드 스크립트에 tail -f 를 남기지 않는다. 종료 조건이 없으므로 세션이 끊겨도 프로세스가 남아 파일 핸들을 붙잡는다. 로테이션된 옛 로그가 삭제되었는데 디스크가 안 비는 원인이 대개 이것이다. lsof | grep deleted 로 확인할 수 있다.
함께 보면 좋은 명령어
- less —
less +F로 같은 실시간 추적을 하면서 위로 되감아 볼 수도 있다. - journalctl — systemd 서비스 로그는 파일이 아니라
journalctl -u 서비스 -f로 본다. - grep — 흐르는 로그에서 관심 있는 줄만 남길 때 짝으로 쓴다.