본문 바로가기

Linux/systemd

[Linux] coredumpctl로 크래시 디버깅하기

앞으로 티스토리 대신 blog.stackframe.dev에서 블로깅을 합니다. 이 블로그는 남겨 둘 예정입니다.

리눅스는 프로그램에서 에러가 나서 크래시되면 coredump 파일을 남기게 할 수 있습니다. 옛날에만 해도 ulimit에 coredump를 남기지 않도록 기본설정이 되어있어서 에러를 확인하고 싶어도 정보가 없었던 적도 있었습니다. 하지만 init에 systemd가 채용되면서 단순히 파일만 남기는게 아니라 systemd가 해당 에러의 내용과 coredump 파일, 시간 등의 기록을 남기는 역할도 맡게 되었습니다.

 

systemd는 이 기록들을 조회하고 관리하기위해 coredumpctl 이란 명령을 제공합니다.

그냥 해당 명령을 실행하면 지금까지 있었던 기록들을 보여줍니다.

참고로 이 기록은 journalctl과 연동됩니다. 사용자가 시스템 전반의 journal에 접근할 권한이 없다면 자신의 coredump 기록만 표시됩니다.

 

coredumpctl은 아래와 같은 인자를 받습니다.

$ coredumpctl [옵션] [명령] [필터]

옵션은 별로 쓸 일은 없을거라 생각되지만 그나마 쓰일 수 있는 몇 가지만 설명하겠습니다.

-1 : 마지막 하나의 coredump 데이터만 가져옵니다.

-S, --since : 시작 날짜를 지정합니다.

-U, --until : 종료 날짜를 지정합니다.

 

한가지 중요한 점은 이 옵션들은 list와 info 명령에서만 적용됩니다. 다른 명령에서는 어떤 효과도 없습니다. 거기다 -1 옵션이 사용되거나 info 명령이면서 필터가 입력되지 않았다면 -S, -U 옵션도 무시됩니다. 저도 이게 안되는게 이상해서 소스코드를 읽어서 확인했습니다.

 

명령은 list, info, dump, dubug가 있습니다.

기본적으로 어떤 명령도 입력하지 않는다면 list로 작동합니다.

info는 coredump의 자세한 정보를 보여줍니다. 어떤 필터도 입력되지 않았다면 최신의 coredump 정보를 가져옵니다.

dump는 coredump를 stdout으로 내보냅니다. info와 마찬가지로 필터가 입력되지 않으면 최신의 coredump를 가져옵니다. 만약 redirection( > >>)이나 --output 옵션이 사용되지 않았다면 바이너리 데이터인 coredump를 내보내는걸 거부합니다.

 

debug는 coredump 데이터를 가지고 디버거를 실행합니다. 필터가 입력되지 않았다면 최신의 coredump에 대한 디버거를 실행합니다.

제가 일부러 coredump를 발생시키고 coredumpctl debug 명령을 실행한 결과입니다. 바로 gdb가 실행되고 backtrace를 통해 free_func에서 문제가 발생했다는 것을 알 수 있습니다.

 

패턴은 PID, 프로세스 이름, 프로세스 경로, journalctl의 match 필터가 쓰입니다. journalctl 매치 필터에 대한 자세한 정보는 systemd.journal-fields(7) 맨페이지를 참고하시기 바랍니다.

 

이 coredumpctl을 활용한다면 매번 gdb에 물려놓고 다시 크래시 날 때까지 문제상황을 재구성하는 시간 낭비를 줄일 수 있을거라 생각됩니다.