SameOS ~/tools/game-server-oom-exit-137.md

게임 서버가 갑자기 꺼질 때: 메모리 부족과 Exit 137 구분하기

작성·공식 문서 확인일 2026-09-07 · SameOS operator

친구들이 동시에 튕겼고 컨테이너에는 Exited (137)만 남았습니다. RAM을 더 주면 해결될까요? 137은 강제 종료를 의심할 신호지만 그 자체가 메모리 부족 판정은 아닙니다. 마지막 종료 시각에 맞춰 게임·컨테이너·커널 기록을 겹쳐 보고, 한도가 부족한 것인지 저장 중 강제로 종료된 것인지 구분해야 합니다.

1. 재생성하기 전에 종료 기록 확보

컨테이너를 삭제하고 새로 만들면 이전 종료 상태를 바로 조회하기 어려워집니다. 우선 이름과 종료 시각, OOMKilled, ExitCode를 기록합니다. inspect 전체 출력에는 환경 변수의 비밀번호가 포함될 수 있어 필요한 필드만 확인합니다.

자동 재시작이 이미 일어났다면 아래 State가 방금 발생한 장애를 그대로 나타내지 않을 수 있습니다. 오래된 컨테이너 이름·ID와 당시 로그를 확보하고 기록이 없으면 원인을 미확인으로 남깁니다.

docker inspect --format 'Exit={{.State.ExitCode}} OOM={{.State.OOMKilled}} Finished={{.State.FinishedAt}} Restarts={{.RestartCount}}' mc-server
docker logs --timestamps --since 30m --tail 200 mc-server

2. Exit 137과 OOMKilled는 다른 증거

일반적인 Unix 종료 표현에서 137은 128+9로 SIGKILL과 연결됩니다. 메모리 부족으로 커널이 죽였을 수도 있지만 관리자의 강제 종료나 정상 종료 대기 시간 초과로도 나타날 수 있습니다. 프로그램이 같은 숫자를 직접 반환할 가능성까지 있으므로 코드만 보고 단정하지 않습니다.

OOMKilled=true라면 Docker가 기록한 OOM 종료 근거입니다. 해당 시각의 커널 메시지에서 대상 프로세스와 메모리 그룹을 맞춰 봅니다. false거나 로그가 비었다는 이유만으로 메모리 문제를 완전히 배제하지는 않습니다. 재부팅·로그 보관·권한 때문에 기록이 없을 수 있습니다.

sudo journalctl -k --since "30 minutes ago" --no-pager
free -h
docker stats --no-stream mc-server

3. 호스트 여유 메모리와 컨테이너 한도를 구분

호스트 RAM이 남아도 컨테이너가 자신의 하드 한도에 도달하면 종료될 수 있습니다. 아래 Memory 값은 바이트이며 0은 Docker의 해당 하드 한도를 따로 두지 않았다는 뜻입니다. 상위 cgroup이나 서비스 관리자가 추가로 제한할 수도 있습니다.

docker stats 한 번의 출력은 지금의 상태입니다. 장애 직전에 월드 생성·다수 접속·백업이 겹친 순간의 최고 사용량을 대신하지 못합니다. 작업 시각과 주기적인 사용량 기록이 있어야 재발 조건을 좁힐 수 있습니다.

docker inspect --format 'Memory={{.HostConfig.Memory}} MemorySwap={{.HostConfig.MemorySwap}}' mc-server

4. Minecraft의 Xmx를 컨테이너 전체 RAM과 같게 잡지 않기

Java의 -Xmx는 힙의 최대 크기입니다. 프로세스 전체에는 메타스페이스, 스레드 스택, 직접 버퍼 등 힙 밖 메모리도 필요합니다. 예를 들어 컨테이너 한도와 Xmx를 모두 6GiB로 맞추면 힙 밖 영역이 쓸 여유를 따로 잡지 않은 구성입니다. 이 숫자는 설명용이며 추천 사양이 아닙니다.

게임 로그의 OutOfMemoryError: Java heap space와 커널이 Java를 죽인 상황은 해결 방향이 다를 수 있습니다. 전자는 힙 사용과 모드의 할당을, 후자는 전체 프로세스와 컨테이너·호스트 한도를 함께 확인합니다. Xmx를 무작정 올리면 두 번째 문제를 악화시킬 수 있습니다.

5. 종료·업데이트 시각에만 발생하면 저장 대기 시간 확인

게임이 월드를 저장하는 동안 컨테이너 종료 대기 시간이 지나면 강제 종료로 이어질 수 있습니다. 업데이트 시작 시각과 종료 로그가 맞물리는지, 저장 완료 메시지가 끝까지 남았는지 먼저 확인합니다. 이것은 플레이 도중 메모리가 차는 문제와 다르게 다뤄야 합니다.

정상 저장 명령과 종료 신호가 게임·이미지에서 어떻게 처리되는지 확인한 뒤 실제 저장 시간을 측정해 여유를 둡니다. 타임아웃만 길게 늘려도 이미 멈춘 프로세스나 잘못된 신호 전달이 해결되는 것은 아닙니다. 반복 강제 종료 후에는 별도 복사본으로 월드 복구 검증을 진행합니다.

6. 설정 변경은 한 가지씩, 같은 플레이 조건으로 검증

근거가 컨테이너 한도라면 호스트의 다른 서비스와 여유를 확인한 뒤 한도를 조정합니다. 특정 모드 추가 뒤부터 증가했다면 운영 월드를 백업하고 복사본에서 모드·로더 조합을 확인합니다. Palworld처럼 Java가 아닌 서버에 Xmx 옵션을 붙이는 것은 해결책이 아닙니다.

정기 재시작은 누적 문제를 잠시 가릴 수 있지만 원인을 설명하지 못합니다. swap 역시 RAM과 같은 속도로 동작하지 않아 게임 지연을 늘릴 수 있습니다. OOM 보호 기능을 꺼서 호스트 전체를 위험하게 만들기보다 메모리 예산과 작업 중첩을 조정합니다.

재발 확인표에는 변경 한 가지, 게임 빌드·모드 버전, 인원, 플레이 시간, 최고 사용량, 저장 성공, 강제 종료 여부를 남깁니다. 한 번 부팅된 것으로 끝내지 말고 문제가 나던 작업과 정상 저장·재시작까지 통과했는지 봅니다.

검증 범위와 공식 참고자료

공식 문서와 명령 옵션을 확인해 작성한 Linux 운영 가이드입니다. 이 글의 경로·서비스명·주소와 진단 상황은 설명용이며 실제 SameOS 게임 서버 장애 기록이나 성능 측정값이 아닙니다. 운영 서버에서 장애를 유발하거나 저장 데이터를 변경하는 실험은 하지 않았습니다. 게임 빌드와 설치 방식에 따라 설정·저장 위치가 다르므로 실제 환경을 확인한 뒤 적용하세요.

SameOS 작성·번역·검수 원칙 보기

Minecraft 렉 줄이는 설정 강제 종료 후 복구 검증 디스크 부족도 확인하기