syslog: 머리, 우선순위, 커널 사건
/var/log/messages 와 /var/log/syslog 에는 데몬, cron, systemd, 커널까지 기계가 하는 말이 다 섞여 있습니다. 장애 때 쓸모 있는 줄은 수천 줄 중 몇 줄입니다. OOM 으로 죽은 프로세스, 디스크 I/O 오류, 종료된 서비스 같은 것입니다.
파일을 이 페이지에 놓으면 보드에 기록이 많은 프로그램, OOM 강제 종료 · segfault · I/O 오류 · 링크 up/down · 시각 동기화 같은 커널 · 시스템 사건이 시간축과 함께 나오고, OOM 과 디스크 I/O 오류는 호스트 · 장치까지 짚어 줍니다. 아래 한 줄 명령은 서버에서 같은 일을 합니다.
머리 형식 두 가지
RFC 3164 (BSD syslog)
예전 정보성 형식이며, 디스크의 파일은 아직 대부분 이 모양입니다.
<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8| 부분 | 예시 값 | 규칙 |
|---|---|---|
| PRI | <34> | facility × 8 + severity 를 꺾쇠 안에 씁니다. 로컬 syslog 데몬이 쓰는 텍스트 파일에는 대개 빠져 있습니다. |
| TIMESTAMP | Oct 11 22:14:15 | "Mmm dd hh:mm:ss", 현지 시각, 24시간제입니다. 연도와 시간대가 없습니다. 10일 미만은 공백으로 채워 "Oct 7" 처럼 공백이 두 칸입니다. |
| HOSTNAME | mymachine | 보낸 쪽의 호스트 이름, IPv4 또는 IPv6 주소입니다. |
| TAG | su | 프로그램 이름이며 영숫자 32자까지, 다른 문자가 오면 거기서 끝나고 CONTENT 가 시작됩니다 — 그래서 su 뒤의 콜론은 이미 CONTENT 입니다. sshd[3011]: 처럼 대괄호 안에 프로세스 번호를 붙이는 경우가 흔합니다. |
| CONTENT | 'su root' failed … | 자유 형식 글입니다. |
날짜가 공백 채움으로 한 자리일 수 있어서 awk 칸 번호는 같지만($1 월, $2 일, $3 시각, $4 호스트, $5 태그) 1~9일에는 글자 위치가 어긋납니다. 연도가 없다는 점은 파일이 새해를 넘길 때 문제가 됩니다.
RFC 5424
지금의 표준은 버전, 완전한 시각, 구조화 데이터를 더합니다.
<165>1 2026-10-18T10:02:11.003Z web-1 app 4242 ID47 [exampleSDID@32473 iut="3"] request timed out| 칸 | 예시 값 | 규칙 |
|---|---|---|
| PRI | <165> | 계산법은 같습니다. 165 = facility 20(local4) × 8 + severity 5(notice). |
| VERSION | 1 | 프로토콜 버전입니다. |
| TIMESTAMP | 2026-10-18T10:02:11.003Z | 소수 초와 시간대를 포함한 날짜 · 시각, 또는 "-". |
| HOSTNAME | web-1 | 255자까지, 또는 "-". |
| APP-NAME | app | 48자까지, 또는 "-". |
| PROCID | 4242 | 128자까지, 또는 "-". |
| MSGID | ID47 | 32자까지, 또는 "-". |
| STRUCTURED-DATA | [exampleSDID@32473 iut="3"] | [id 이름="값"] 요소 0개 이상, 또는 "-". |
| MSG | request timed out | 메시지입니다. |
facility 와 severity
PRI 에는 숫자 두 개가 들어 있습니다. PRI = facility × 8 + severity 이므로 facility 는 int(PRI / 8), severity 는 PRI % 8 입니다. <0> 은 kern.emerg, <165> 는 local4.notice 입니다.
| severity | 이름 |
|---|---|
| 0 | Emergency — 시스템을 쓸 수 없음 |
| 1 | Alert — 즉시 조치해야 함 |
| 2 | Critical |
| 3 | Error |
| 4 | Warning |
| 5 | Notice — 정상이지만 중요한 상황 |
| 6 | Informational |
| 7 | Debug |
| facility | 이름 |
|---|---|
| 0 | 커널 메시지 |
| 1 | 사용자 수준 |
| 2 | 메일 |
| 3 | 시스템 데몬 |
| 4 | 보안 · 인가 |
| 5 | syslogd 내부 |
| 6 | 라인 프린터 |
| 7 | 네트워크 뉴스 |
| 8 | UUCP |
| 9 | 시계 데몬 |
| 10 | 보안 · 인가 |
| 11 | FTP 데몬 |
| 12 | NTP |
| 13 | 로그 감사 |
| 14 | 로그 경보 |
| 15 | 시계 데몬 |
| 16–23 | local0 – local7 |
찾을 만한 커널 · 시스템 사건
OOM 킬러는 중요한 줄 두 개를 씁니다. 무엇이 일으켰는지, 무엇을 죽였는지입니다. 커널 소스(6.x) 기준입니다.
Oct 18 10:02:11 web-1 kernel: java invoked oom-killer: gfp_mask=0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=0
Oct 18 10:02:11 web-1 kernel: Out of memory: Killed process 4242 (java) total-vm:8123456kB, anon-rss:6012344kB, file-rss:0kB, shmem-rss:0kB, UID:1001 pgtables:12345kB oom_score_adj:0
Oct 18 10:02:12 web-1 systemd[1]: app.service: Main process exited, code=killed, status=9/KILL<task> invoked oom-killer:— 메모리 할당에 실패한 태스크입니다. 죽은 프로세스와 같다는 보장이 없습니다.Out of memory: Killed process <pid> (<이름>)— 희생된 프로세스와 그 순간의 가상 크기, 상주 메모리(anon-rss · file-rss · shmem-rss)입니다. 한도가 cgroup 이었다면 "Memory cgroup out of memory" 로 시작합니다.- 그다음 줄은 대개 서비스 관리자가 알아챈 기록입니다. systemd 의
code=killed, status=9/KILL은 같은 사건을 서비스 쪽에서 본 것입니다.
그 밖에 시간축에 올려 볼 줄: 세그멘테이션 오류(segfault at), 블록 I/O 오류(I/O error, dev sdb), 파일 시스템 오류, NIC 링크 변화. 정확한 문구는 커널 버전과 드라이버에 따라 다르므로 문장 전체보다 짧은 패턴을 대소문자 구분 없이 찾으십시오.
syslog 파일용 한 줄 명령
RFC 3164 모양(PRI 없음)의 표본 /var/log/messages 와 작은 RFC 5424 파일로 실행해 확인했습니다. systemd 호스트에서는 journalctl -k 가 커널 메시지를, journalctl -o short 가 같은 배치의 줄을 내므로 같은 파이프가 동작합니다.
줄을 가장 많이 쓰는 프로그램(pid 제거)
awk '{print $5}' messages | sed -E 's/\[[0-9]+\]//; s/:$//' | sort | uniq -c | sort -rn | head여러 서버가 한 파일에 쓸 때 호스트별 줄 수
awk '{print $4}' messages | sort | uniq -c | sort -rnOOM 킬러가 죽인 프로세스 수
grep -cE '(Out of memory|Memory cgroup out of memory): Killed process' messages죽은 프로세스 이름
grep -oE 'Killed process [0-9]+ \([^)]+\)' messages | awk '{print $4}' | tr -d '()' | sort | uniq -c | sort -rnOOM 킬러를 일으킨 태스크
grep -oE '[^ ]+ invoked oom-killer' messages | sort | uniq -csegfault 로 죽은 프로그램
grep -oE '[^ ]+\[[0-9]+\]: segfault at' messages | cut -d[ -f1 | sort | uniq -c | sort -rnI/O 오류를 말하는 줄 수
grep -ciE 'i/o error' messages분당 줄 수 — 몰린 구간이 드러납니다
cut -c1-12 messages | uniq -c호스트별 시간당 줄 수
awk '{split($3, t, ":"); print $4, t[1] ":00"}' messages | sort | uniq -cerror · fail · timed out 이 든 줄을 쓰는 프로그램
grep -iE 'error|fail|timed out' messages | awk '{print $5}' | sed -E 's/\[[0-9]+\]//; s/:$//' | sort | uniq -c | sort -rnRFC 5424: PRI 를 facility 와 severity 로 풀기
grep -oE '^<[0-9]+>' syslog5424.log | tr -d '<>' | awk '{print "facility", int($1/8), "severity", $1%8}' | sort | uniq -cRFC 5424: 호스트 · 앱 이름별 줄 수
awk '{print $3, $4}' syslog5424.log | sort | uniq -c | sort -rn
자주 묻는 질문
RFC 3164 와 RFC 5424 는 무엇이 다른가요?
RFC 3164 는 예전 BSD 형식을 설명합니다. PRI, 연도 · 시간대 없는 시각, 호스트, 자유 형식 태그입니다. RFC 5424 는 그것을 대신한 표준이며 버전 번호, 시간대까지 든 완전한 시각, 앱 이름 · 프로세스 번호 · 메시지 ID 칸, 구조화 데이터가 있습니다.
PRI 숫자에서 facility 와 severity 는 어떻게 구하나요?
facility 는 PRI 를 8 로 나눈 몫, severity 는 나머지입니다. <34> 는 facility 4(보안 · 인가), severity 2(critical)입니다.
/var/log/messages 에 연도가 없는 이유는?
RFC 3164 시각 형식에 연도가 없기 때문입니다. 도구는 올해로 가정하므로 새해를 넘기는 파일에서 틀립니다. RFC 5424 시각에는 연도와 시간대가 있습니다.
OOM 킬러가 무엇을 죽였는지 어떻게 찾나요?
"Out of memory: Killed process" 를 찾으십시오. 뒤에 pid 와 프로세스 이름, 그 순간의 메모리가 나옵니다. 바로 앞 줄이 어떤 태스크가 OOM 킬러를 불렀는지 말해 줍니다.
날짜 뒤에 공백이 두 칸인 이유는?
RFC 3164 가 10일 미만을 공백으로 채우기 때문입니다. "Oct 7" 은 공백이 두 칸입니다. awk 는 연속 공백으로 나누므로 영향이 없지만 cut -d" " 는 영향을 받습니다.
journald 출력도 읽나요?
journalctl 의 기본 short 형식으로 내보낸 글은 syslog 파일과 배치가 같아 보드에 놓으면 됩니다. JSON 으로 내보낸 것은 JSON 줄로 읽습니다.