Linux 종료 코드 137만으로 OOM을 단정할 수 없는 이유

명령이 Killed로 끝나거나 컨테이너 종료 코드가 137이면 SIGKILL과의 관계부터 확인합니다. 메모리 부족은 가능한 원인 중 하나지만 운영자 신호, supervisor 제한 시간, 컨테이너 종료 처리도 같은 신호를 만들 수 있습니다.

메모리 부족 없이도 같은 종료 신호가 나왔다

대기만 하는 작은 Python 자식 프로세스를 만들고 그 프로세스에만 SIGKILL을 보냈습니다. Python의 returncode는 -9였고 일반적인 셸 표현은 128+9=137입니다. 이 실험은 OOM을 만들지 않았습니다. 따라서 137을 봤다는 사실 하나로 메모리를 늘려야 한다는 결론은 성립하지 않습니다.

같은 시각·같은 cgroup의 증거를 모은다

journalctl -k --since "2026-09-21 00:00:00" --no-pager
systemctl show example.service -p Result -p ExecMainCode -p ExecMainStatus -p ControlGroup -p MemoryMax

시각과 example.service는 실제 사건으로 바꿉니다. 커널 OOM 기록의 프로세스와 종료 시각을 맞추고, cgroup v2에서는 해당 서비스의 memory.events와 memory.events.local을 확인합니다. oom_kill은 누적값이므로 한 번의 현재 값보다 사건 전후 증가가 유용합니다. 계층 집계 차이는 cgroup v2 문서의 memory.events 설명과 대조합니다.

권한 부족으로 journal을 못 읽었거나 로그가 회전됐다면 “OOM 없음”이 아니라 증거 미확보입니다. 시스템 전체 available 메모리가 남아 있어도 서비스 cgroup 제한을 먼저 만날 수 있습니다. 반대로 OOM 기록이 없고 stop timeout과 SIGKILL 시각이 같으면 종료 절차를 조사해야 합니다.

확인된 원인에 따라 동시 실행 수·배치 크기·메모리 제한 또는 종료 유예 시간을 한 가지씩 조정하고 같은 작업에서 재발과 메모리 추이를 봅니다. 운영 서버를 일부러 메모리 부족 상태로 만드는 검증은 필요하지 않습니다.