cat 말고 less, tail -f 로 journalctl 로그 분석 방법

Views: 0

왜 cat 대신 다른 도구를 써야 할까

cat은 파일 전체를 한 번에 표준출력으로 밀어내기 때문에 수십 MB 이상 로그에서 비효율적이다. 스크롤·검색·필터링 기능도 없어 사람이 눈으로 따라가기가 어렵다. 반면 less는 대용량 파일을 즉시 열어 페이지 단위로 탐색하고, tail -f는 새로 써지는 줄만 실시간으로 붙여 보여주며, journalctl은 systemd 기반 서비스 로그를 구조적으로 필터링한다. 상황에 맞게 이 셋을 조합하면 탐색 속도와 정확도가 크게 올라간다.

less로 대용량 로그를 빠르게 훑는 법

less는 “읽기 전용 뷰어”다. 기본 동작을 손에 익히면 cat보다 훨씬 빠르다.

필수 옵션과 단축키

  • 줄 넘김 없이 가로 스크롤 허용:
    less -S /var/log/nginx/access.log
  • ANSI 색상 보존(파이프에서 색상 유지):
    ... | less -R
  • 파일 끝으로 즉시 이동: G
  • 파일 처음으로 이동: g
  • 페이지 위/아래: Space, b
  • 줄 단위 이동: j, k
  • 앞으로 검색: /에러패턴 → 다음/이전 결과 n/N
  • 뒤로 검색: ?에러패턴
  • 현재 뷰 필터(매우 유용): &정규식 (해제는 &만 입력)

색상 하이라이트와 조합

grep의 색상을 살려서 less에 넘기면 시인성이 확 올라간다.

grep --color=always -E "ERROR|WARN" app.log | less -R

JSON 로그라면 키워드만 뽑아 하이라이트한다.

jq -r '.level + " " + .msg' app.json.log | grep --color=always -E "ERROR|WARN|Timeout" | less -R

압축 로그 한 번에 보기

로테이션된 gz 로그까지 이어서 본다.

zgrep -h --color=always "ERROR" /var/log/app.log /var/log/app.log.1.gz | less -R

단순 열람은 zless가 편하다.

zless /var/log/nginx/access.log.1.gz

tail -f로 실시간 추적을 제대로 하는 법

실시간 추적은 tail -f가 기본이지만, 로테이션을 고려해 -F를 쓰는 습관이 중요하다.

-f와 -F의 차이

  • tail -f: 파일 디스크립터를 붙잡고 따라간다. 로테이션(rename) 후 새 파일은 못 따라감.
  • tail -F: 파일명이 같은 새 로그로 교체돼도 자동 추적한다. 실무 기본값으로 추천.

즉시 전줄부터 따라가기

서비스 재시작 직후의 힌트를 놓치지 않으려면 최근 N줄과 함께 추적한다.

tail -n 200 -F /var/log/app.log

라인 버퍼링으로 실시간 필터

grep·awk는 버퍼링 때문에 늦게 출력될 수 있다. 실시간은 라인 버퍼링 옵션을 쓴다.

tail -F app.log | grep --line-buffered -E "ERROR|WARN|Timeout"
tail -F access.log | awk -W interactive '$9 ~ /5[0-9][0-9]/ {print $0}'

특정 프로세스만 추적

PID가 있는 경우:

tail -F app.log | grep --line-buffered "pid=12345"

여러 파일 동시 추적

마이크로서비스를 묶어 본다.

tail -F /var/log/app/*.log | ts '[%Y-%m-%d %H:%M:%S]'   # moreutils의 ts 사용 시

journalctl로 systemd 서비스 로그를 정밀 필터링

systemd 환경에서는 journalctl이 sshd, nginx, custom 서비스의 표준 로그 뭉치를 한 번에 다룬다.

서비스 단위로 필터

journalctl -u nginx --since "30 min ago"
journalctl -u sshd -f                      # 실시간 추적
journalctl -u myapp.service -n 200         # 최근 200줄

시간·부팅·중요도 기준

journalctl --since "2025-10-23 10:00" --until "2025-10-23 11:00"
journalctl -b -1                           # 이전 부팅 시퀀스
journalctl -p warning..emerg               # 경고 이상만

빠른 문자열 검색과 정규식

journalctl -u myapp --grep="Timeout|failed to connect" -f

JSON·필드 기반 출력

머신 가공용으로는 JSON 출력이 적합하다.

journalctl -u myapp -o json | jq -r '[.ts,.PRIORITY,.MESSAGE] | @tsv'

컬러를 보려면 페이저 해제:

journalctl -u myapp --no-pager -o short-iso-precise

상황별 실전 패턴 모음

SSH 공격 급증 감지

최근 15분간 실패 10회 이상 IP 상위 10개 추출:

journalctl -u sshd --since "15 min ago" \
| grep "Failed password" \
| awk '{for(i=1;i<=NF;i++) if ($i ~ /([0-9]{1,3}\.){3}[0-9]{1,3}/) print $i}' \
| sort | uniq -c | sort -nr | head

Nginx 5xx 폭증 원인 파악

상위 URL과 IP를 빠르게 집계한다.

awk '$9 ~ /^5/ {print $7}' /var/log/nginx/access.log \
| sort | uniq -c | sort -nr | head

awk '$9 ~ /^5/ {print $1}' /var/log/nginx/access.log \
| sort | uniq -c | sort -nr | head

실시간으로 보면:

tail -F /var/log/nginx/access.log | awk -W interactive '$9 ~ /^5/'

애플리케이션 에러 스택 탐색

스택 트레이스는 여러 줄로 이어지는 경우가 많다. “Anchor → 컨텍스트 확장” 방식이 효율적이다.

grep -n "NullPointerException" app.log | head
# 번호 확인 후
nl -ba app.log | sed -n '1200,1300p' | less

배포 직후만 골라보기

특정 시각 이후만 추적하면 잡음이 줄어든다.

journalctl -u myapp --since "2025-10-23 14:05"

색상 하이라이트로 빠른 패턴 인식

grep --color=always -E "ERROR|WARN|Timeout|Refused" app.log | less -R

로테이션·압축·보존 정책과의 궁합

  • logrotate가 동작하면 파일이 rename되고 새 파일이 열린다. 실시간 추적은 tail -F를 사용한다.
  • 과거 이슈 회고는 gz까지 범위를 넓혀 zgrep·zless로 본다.
  • 보존 주기가 짧다면 문제 발생 시점의 로그를 즉시 백업해 증거를 확보한다.

성능을 해치지 않는 사용 습관

  • 거대한 파일을 통으로 grep하지 말고 시간으로 좁혀라(journalctl의 --since, --until).
  • 정규식은 필요한 그룹만 최소화하고, 파이프는 두세 단계 내로 단순하게 유지한다.
  • 반복 조회하는 패턴은 함수로 alias 정의해 휴먼 에러를 줄인다.
alias jerr='journalctl -p err..emerg --no-pager -o short-iso'
alias japp='journalctl -u myapp --no-pager -o short-iso'

팀 작업을 위한 출력 형식 표준화

  • 운영 채널 공유를 위해 ISO 타임스탬프 출력(-o short-iso-precise)을 통일한다.
  • JSON 로그는 jq 템플릿을 정해 핵심 필드만 뽑는다.
  • 이슈 티켓에는 “증상 → 관련 로그 스냅샷 → 시간 범위 → 재현 절차” 순으로 기록한다.

흔한 실수와 빠른 교정 팁

  • cat으로 수백 MB를 터미널에 뿌려 터미널이 멎는 문제: less로 열고 필요 시 /패턴 검색.
  • tail -f가 로테이션 후 끊기는 문제: -F로 교체.
  • journalctl 결과가 너무 많아 스크롤이 힘든 문제: -u, -p, --since로 필터부터 적용.
  • 색상 사라짐: --color=always | less -R 조합 사용.
  • 실제 클라이언트 IP가 보이지 않음: 리버스 프록시 환경에서는 로그 포맷과 real IP 설정을 점검.

실무용 치트시트

# 최근 10분 nginx 5xx만 색상 하이라이트
awk -v T="$(date -d '-10 min' +'%d/%b/%Y:%H:%M')" '$4 ~ T && $9 ~ /^5/' /var/log/nginx/access.log \
| grep --color=always -E "HTTP/| 5[0-9]{2} " | less -R -S

# sshd 경고 이상만, ISO 타임스탬프
journalctl -u sshd -p warning..emerg --since "1 hour ago" -o short-iso --no-pager

# 앱 로그 에러를 실시간으로, 라인 버퍼링
tail -F /var/log/app/app.log | grep --line-buffered -E "ERROR|Exception"

# gz 포함 특정 에러 키워드 종합 조회
zgrep -h --color=always -E "OutOfMemory|Timeout" /var/log/app/app.log* | less -R

마무리

로그 읽기의 핵심은 “목표를 좁히고, 필요한 줄만 빨리 보는 것”이다. less로 대용량을 빠르게 탐색하고, tail -F로 현재 진행형 이슈를 붙잡으며, journalctl로 서비스·시간·중요도 축을 정교하게 필터링하면 추적 속도가 눈에 띄게 향상된다. 위의 패턴을 그대로 손에 익히면 배포 문제, 성능 저하, 보안 이벤트까지 터미널 하나로 신속하게 진단할 수 있다.