우분투 실전 명령어 | sort uniq로 로그 빈도 집계

서버 로그에서 같은 에러가 얼마나 반복되는지 빠르게 보고 싶을 때가 많습니다. 이럴 때 sort, uniq, cut, tr 조합만 잘 써도 원인 후보를 금방 좁힐 수 있습니다.

언제 쓰는가

  • access/error 로그에서 가장 많이 발생한 값 상위 N개를 보고 싶을 때
  • CSV/공백 구분 텍스트에서 특정 컬럼 기준 빈도 집계를 할 때
  • 장애 초기에 어떤 패턴이 비정상적으로 늘었는지 빠르게 확인할 때

바로 쓰는 명령어

# IP별 요청 수 상위 20개
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20

# 상태코드별 건수
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr

# 에러 로그에서 "timeout" 라인이 시간 접두어를 제외하고 몇 번 나왔는지
grep 'timeout' /var/log/app/error.log | cut -d' ' -f5- | sort | uniq -c | sort -nr | head
# 대소문자/구분자 정규화 후 빈도 집계
cat app-events.log \
  | tr '[:upper:]' '[:lower:]' \
  | tr ',' '\n' \
  | sed 's/^ *//; s/ *$//' \
  | grep -v '^$' \
  | sort | uniq -c | sort -nr | head -30

핵심 옵션/패턴

  • uniq -c: 중복 줄 개수를 앞에 붙여서 출력
  • sort -nr: 숫자 기준 내림차순 정렬, 빈도 상위부터 확인 가능
  • cut -d -f: 구분자와 필드 번호로 필요한 컬럼만 잘라냄
  • tr: 문자 치환이나 줄바꿈 변환에 유용, 전처리 속도가 빠름
  • 집계 전에 정규화 먼저: 대소문자, 공백, 구분자를 맞춰야 같은 항목이 정확히 합산됨

명령 출력 예시

$ awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
  918 200
  127 404
   39 499
   11 500
$ grep 'timeout' /var/log/app/error.log | cut -d' ' -f5- | sort | uniq -c | sort -nr | head
  84 upstream timeout while reading response header from upstream
  23 db timeout after 3s while acquiring connection
   7 rpc timeout reached retry limit

자주 하는 실수

  • sort 없이 uniq -c를 먼저 실행함
    • uniq는 인접한 중복만 합치므로 정렬 없이 쓰면 집계가 틀어질 수 있음
  • cut 필드 번호를 로그 포맷과 다르게 가정함
    • nginx 커스텀 포맷이면 상태코드가 9번째 필드가 아닐 수 있음
  • head만 보고 전체 분포를 단정함
    • 상위 몇 개만 보면 하위 패턴의 급증을 놓칠 수 있음

검증 방법

# 원본 라인 수와 집계 합계가 맞는지 확인
TOTAL=$(awk '{print $9}' /var/log/nginx/access.log | wc -l)
SUM=$(awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | awk '{s+=$1} END{print s}')
echo "total=$TOTAL sum=$SUM"

# 특정 값 재검증 (예: 404)
grep -c ' 404 ' /var/log/nginx/access.log
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | grep ' 404$'

운영 팁

  • 자주 보는 집계는 함수로 만들어 두면 장애 때 실수를 줄일 수 있음
  • 로그 로테이션 환경에서는 zgrep, zcat까지 함께 써서 기간 누락을 방지하는 편이 안전함
  • 집계 명령 앞단에 timeout 10s를 걸어 두면 대용량 로그에서도 터미널 점유를 줄일 수 있음

출처

  • GNU Coreutils
  • util-linux
  • NGINX Documentation