사전 dmesg
인터페이스

dmesg

gabury1고친 사람 github-actions[bot]

dmesg 는 운영체제의 핵심부가 남긴 메시지를 보여 주는 명령입니다. 장치를 찾았다는 알림부터 메모리가 바닥나 프로세스를 끝냈다는 기록까지 이 메시지에 남습니다. 애플리케이션 로그에 아무 흔적도 없이 프로세스가 사라졌을 때 가장 먼저 열어 보는 명령입니다.

쉽고 빠른 이해

dmesg 는 운영체제가 스스로 적어 둔 일지를 읽어 주는 명령입니다. 서버에서 자바 프로세스가 말없이 사라졌을 때 dmesg 를 치면 「메모리가 모자라 이 프로세스를 끝냈다」는 줄이 보이는 식입니다.

운영체제가 프로그램을 강제로 끝내면 그 프로그램은 마지막 로그 한 줄도 못 남깁니다. 이 일지를 안 보면 왜 사라졌는지 모른 채 남습니다.

  1. 운영체제는 장치나 메모리에 일이 생길 때마다 메모리 안의 정해진 공간에 한 줄씩 적습니다
  2. 공간이 차면 가장 오래된 줄을 지우고 새 줄을 적습니다
  3. dmesg 는 이 공간에 남은 줄을 시간 순으로 찍습니다

대가가 있습니다. 일지가 메모리에만 있어서 재부팅하면 사라집니다. 오래된 줄도 새 줄에 덮여 없어집니다. 지난 기록은 일지를 디스크에 옮겨 두는 로그 도구에서 찾아야 합니다.

상세

dmesg 는 리눅스와 FreeBSD 같은 유닉스 계열 운영체제에 들어 있는 명령입니다. 이 절은 리눅스를 기준으로 씁니다. 이름이 무엇의 줄임인지는 확인 못 했습니다(미확인).

백엔드 개발자가 이 명령을 꺼내는 때는 대개 정해져 있습니다. 프로세스가 로그 없이 사라졌을 때, 디스크나 네트워크가 이상할 때입니다. 이런 일은 애플리케이션 밖에서 벌어집니다. 그래서 애플리케이션 로그에는 안 남고 운영체제 쪽 기록에만 남습니다.

이 절은 먼저 운영체제가 그 기록을 어디에 어떻게 남기는지 봅니다. 그다음 출력 한 벌을 읽습니다. 이어서 장애 때 어떤 줄을 찾는지 봅니다. 끝으로 이 명령이 못 보는 것과 그때 대신 쓰는 도구를 봅니다.

커널 로그

운영체제에서 하드웨어를 직접 다루고 프로세스에 메모리를 나눠 주는 핵심부를 커널이라 합니다. 애플리케이션은 파일을 열거나 메모리를 받을 때마다 커널에 부탁합니다.

커널도 일하면서 알릴 것이 생깁니다. 디스크를 찾았다, 네트워크 선이 빠졌다, 메모리가 바닥나 프로세스 하나를 끝냈다 같은 것입니다. 커널이 이런 알림을 한 줄씩 남긴 것을 커널 로그라 부릅니다. dmesg 가 보여 주는 것이 이 커널 로그입니다.

커널 로그는 장치를 다루는 코드에서 특히 많이 나옵니다. 커널 안에서 장치 하나를 맡아 다루는 코드를 디바이스 드라이버라 합니다. 드라이버는 장치를 찾았을 때와 장치와 주고받다 실패했을 때 그 내용을 커널 로그에 적습니다.

링 버퍼

커널은 메시지를 처음에 파일이 아니라 메모리에 적습니다. 컴퓨터가 막 켜지는 동안에는 디스크의 파일 시스템을 아직 못 쓰기 때문입니다. 그래서 커널은 메모리에 정해진 크기의 공간을 잡아 두고 거기에 적습니다. 커널 코드는 printk 라는 함수를 불러 이 공간에 한 줄을 적습니다.

이 공간은 링 버퍼입니다. 링 버퍼는 끝까지 차면 맨 앞으로 돌아가 가장 오래된 줄 위에 새 줄을 덮어쓰는 버퍼입니다. 크기가 늘지 않으니 메모리를 일정하게만 씁니다. 대신 메시지가 쏟아지면 오래된 줄이 금방 사라집니다.

dmesg 는 이 링 버퍼에 지금 남아 있는 줄을 읽어 찍습니다. 링 버퍼의 줄을 가져다 따로 모아 두는 프로그램도 돕니다. 이 글은 그런 프로그램을 로그 수집 프로그램이라 부릅니다. 로그 수집 프로그램은 대개 모은 줄을 디스크에 옮겨 적습니다. 다만 설정에 따라 메모리에만 두기도 합니다.

한 줄의 메시지가 지나가는 길은 아래와 같습니다.

flowchart TD
    A["커널 코드 · 디바이스 드라이버"] -->|"printk 로 한 줄 적는다"| B["링 버퍼 · 메모리 안"]
    B -->|"읽어서 찍는다"| C["dmesg"]
    B -->|"옮겨 적는다"| D["로그 수집 프로그램"]
    D --> E["디스크의 로그 파일"]

갈래가 둘인 까닭은 오래 남기느냐에 있습니다. dmesg 가 읽는 링 버퍼는 재부팅하면 비워집니다. 디스크로 옮긴 쪽은 재부팅 뒤에도 남습니다.

출력 모양

아래는 dmesg 출력의 일부입니다. 줄은 예로 지어낸 것입니다. 길어서 뒤를 ... 로 줄였습니다.

[    0.000000] Linux version ...
[    2.314502] eth0: Link is Up ...
[86412.207133] Out of memory: Killed process 4321 (java) ...
[90120.551820] app[5170]: segfault ...

줄 맨 앞 대괄호 안의 숫자는 컴퓨터가 켜진 뒤 흐른 초입니다. 첫 줄의 0 초는 커널이 막 깨어난 순간입니다. 셋째 줄의 86412 초는 켜진 지 하루쯤 지난 때입니다.

대괄호 뒤가 메시지 본문입니다. 둘째 줄의 eth0 은 네트워크 인터페이스 이름입니다. 이 줄은 그 선이 연결됐다는 알림입니다. 셋째 줄은 메모리가 바닥나 커널이 java 프로세스를 끝냈다는 기록입니다. 넷째 줄은 app 프로세스가 잘못된 메모리 주소를 건드려 끝났다는 기록입니다. 이 두 줄은 아래 「장애 때 찾는 줄」에서 다시 읽습니다.

메시지 등급

커널은 메시지마다 얼마나 급한지를 나타내는 등급을 붙입니다. 등급은 0 부터 7 까지 여덟 개입니다. 숫자가 작을수록 급합니다. 기본 출력에는 등급이 안 보입니다. 대신 옵션으로 등급을 골라 걸러 볼 수 있습니다.

숫자 이름 뜻
0 emerg 시스템을 쓸 수 없는 상태
1 alert 바로 손써야 하는 상태
2 crit 치명적인 상태
3 err 오류
4 warn 경고
5 notice 정상이지만 눈여겨볼 일
6 info 알림
7 debug 디버깅용 메시지

장애를 볼 때는 흔히 err 와 warn 만 걸러 봅니다. 평소에 쌓이는 알림 줄이 빠져서 문제가 된 줄이 잘 보입니다.

장애 때 찾는 줄

이 소절은 백엔드 개발자가 dmesg 를 여는 네 가지 경우를 봅니다. 경우마다 찾을 낱말과 그 줄의 뜻을 짝지어 적습니다.

로그 없이 사라진 프로세스. 메모리가 바닥난 상태를 OOM(Out Of Memory, 메모리 부족)이라 합니다. 이때 커널은 프로세스 하나를 골라 강제로 끝냅니다. 이 일을 하는 커널 기능이 OOM 킬러입니다.

OOM 킬러에 끝난 프로세스는 마지막 로그를 남길 틈이 없습니다. 프로세스를 띄운 쪽에는 강제로 끝났다는 뜻의 종료 코드 137 만 돌아옵니다. 그래서 dmesg | grep -i "out of memory" 로 커널 로그를 찾아야 원인이 드러납니다. 위 출력의 셋째 줄이 그 기록입니다.

세그멘테이션 폴트. 프로세스가 자기 것이 아닌 메모리 주소를 건드리면 커널이 그 프로세스를 끝냅니다. 이것을 세그멘테이션 폴트라 합니다. 커널은 이때 프로세스 이름과 번호를 segfault 라는 낱말과 함께 남깁니다. 위 출력의 넷째 줄입니다. C 로 짠 네이티브 라이브러리를 부르는 애플리케이션이 말없이 죽으면 이 줄을 찾습니다.

디스크 입출력 오류. 디스크가 읽기나 쓰기에 실패하면 드라이버가 I/O error 가 든 줄을 남깁니다. I/O 는 Input/Output(입출력)의 줄임입니다. 오류가 이어지면 리눅스는 데이터를 지키려고 파일 시스템을 읽기만 되게 바꾸기도 합니다. 애플리케이션이 갑자기 파일을 못 쓰게 되면 이 줄을 찾아봅니다.

네트워크 연결 끊김. 네트워크 선이 끊기거나 다시 붙으면 드라이버가 Link is Down 이나 Link is Up 같은 줄을 남깁니다. 정확한 문구는 드라이버마다 다릅니다. 요청 실패가 잠깐 몰린 시각에 이 줄이 있으면 애플리케이션이 아니라 연결이 끊긴 것입니다.

자주 붙이는 옵션

옵션 없이 치면 링 버퍼 전체를 처음부터 찍습니다. 줄이 많아서 장애를 볼 때는 아래처럼 범위를 좁혀 봅니다.

dmesg -T            # 시각을 날짜로 찍음
dmesg -l err,warn   # 오류와 경고만
dmesg -w            # 새 줄을 기다려 찍음
dmesg | tail -20    # 마지막 20줄만

-w 는 장애를 다시 일으켜 보면서 커널 로그를 지켜볼 때 씁니다. 끊을 때까지 새 줄이 생기는 대로 찍습니다.

-c 는 찍은 다음 링 버퍼를 비웁니다. 다른 사람이 봐야 할 기록까지 지워지므로 장애를 조사할 때는 안 붙입니다.

시각을 읽을 때

기본 시각은 켜진 뒤 흐른 초라서 장애가 난 시각과 맞춰 보기 어렵습니다. -T 는 이 초에 부팅 시각을 더해 날짜와 시각으로 바꿔 찍습니다.

-T 가 찍는 시각은 어긋날 수 있습니다. 컴퓨터가 절전 상태였던 동안은 이 초가 흐르지 않아서 그만큼 시각이 앞당겨져 찍힙니다. 절전하지 않고 늘 켜져 있는 서버에서는 대개 맞습니다. 노트북에서 본 시각은 다른 로그와 맞춰 보기 전에 의심해 봅니다.

읽기 권한

배포판은 우분투처럼 리눅스 커널에 여러 프로그램을 묶어 내놓은 운영체제입니다. 배포판에 따라 일반 사용자는 dmesg 를 못 치게 막혀 있습니다. 커널 로그에는 메모리 주소처럼 공격에 쓰일 수 있는 정보가 섞이기 때문입니다. 그때는 관리자 권한으로 명령을 치게 해 주는 sudo 를 앞에 붙여 sudo dmesg 로 칩니다.

막을지 말지는 커널 설정값 kernel.dmesg_restrict 가 정합니다. 1 이면 관리자만 읽습니다. 0 이면 누구나 읽습니다.

컨테이너 안에서

컨테이너는 한 기계 위에서 프로세스를 따로 떼어 돌리는 방식입니다. 컨테이너를 띄운 기계를 호스트라 부릅니다.

컨테이너는 호스트와 커널을 함께 씁니다. 커널이 하나이니 링 버퍼도 호스트에 하나뿐입니다. 그래서 컨테이너가 메모리 한도를 넘어 OOM 킬러에 끝나도 그 기록은 호스트의 커널 로그에 남습니다.

컨테이너 안에서 dmesg 를 치면 흔히 권한이 없다고 거절됩니다. 컨테이너가 왜 끝났는지 찾을 때는 호스트에 들어가 dmesg 를 칩니다.

재부팅 뒤에 지난 기록 찾기

서버가 갑자기 재부팅된 뒤에 원인을 찾으려고 dmesg 를 치면 새 부팅의 메시지만 보입니다. 링 버퍼가 재부팅과 함께 비워졌기 때문입니다. 지난 부팅의 커널 로그는 로그 수집 프로그램이 디스크에 옮겨 두었을 때 거기서 찾습니다.

systemd 는 다른 프로그램을 띄우고 관리하는 프로그램입니다. 많은 리눅스 서버에서는 systemd 에 딸린 journald 가 로그 수집 프로그램 노릇을 합니다.

journald 가 모은 로그는 journalctl 명령으로 읽습니다. 이름이 비슷하지만 journald 는 모으는 쪽입니다. journalctl 은 읽는 쪽입니다.

journalctl -k        # 이번 부팅의 커널 로그
journalctl -k -b -1  # 바로 전 부팅의 것

-k 는 커널 로그만 고릅니다. -b -1 은 바로 전 부팅을 고릅니다. 전 부팅의 것은 journald 가 로그를 디스크에 남기도록 설정돼 있을 때만 보입니다.

journald 대신 syslog 계열 프로그램이 도는 서버도 있습니다. 그때는 배포판에 따라 /var/log/kern.log 나 /var/log/messages 같은 파일에 커널 로그가 남습니다.

dmesg 가 못 보는 것

dmesg 는 커널이 본 일만 보여 줍니다. 애플리케이션이 예외를 던지거나 요청이 느려진 것은 커널이 모르는 일이라 안 나옵니다.

링 버퍼 크기만큼만 남는다는 한계도 있습니다. 오래 켜 둔 서버에서는 부팅 때 장치를 찾던 메시지가 이미 덮여 안 보일 수 있습니다.

그래서 보려는 것에 따라 도구를 나눠 씁니다.

보려는 것 쓰는 도구
지금 링 버퍼에 남은 커널 메시지 dmesg
지난 부팅까지 포함한 커널 메시지 journalctl -k · 시스템 로그 파일
프로세스가 던진 예외와 요청 기록 애플리케이션 로그
메모리 · 디스크 같은 자원을 쓰는 흐름 vmstat · sar

관련 항목

dmesg 가 읽어 보여 주는 커널 기록

커널 로그 · 링 버퍼 · printk · 로그 레벨 · 커널 · 디바이스 드라이버

dmesg 로 원인을 찾는 장애

OOM 킬러 · 세그멘테이션 폴트 · 입출력 오류 · 커널 패닉 · 종료 코드 · SIGKILL · 스와핑

커널 로그를 디스크에 옮겨 두는 도구

journalctl · journald · syslog · rsyslog · systemd · 로그 로테이션

dmesg 와 함께 쓰는 진단 명령

vmstat · sar · top · iostat · free · strace · grep · tail

dmesg 가 도는 운영체제와 격리 환경

Linux · FreeBSD · 유닉스 · 운영체제 · 컨테이너 · cgroup · 네임스페이스

dmesg 를 꺼내는 성능 분석 틀

성능 · 성능 분석 · USE 방법 · 장애 대응

다른 이름: dmesg 명령 · 디메시지