اگر هنگام اجرای یک برنامه روی سرور لینوکسی فقط پیام Killed میبینید، یا یک Container در Docker با Exit Code 137 متوقف میشود، اولین حدس معمولاً OOM Killer است؛ اما این نتیجه همیشه درست نیست. کد 137 یعنی فرایند با سیگنال SIGKILL متوقف شده است. کمبود RAM و فعالشدن OOM Killer یکی از علتهای رایج این وضعیت است، ولی Kill دستی، محدودیت حافظه Container یا بعضی Timeoutها نیز میتوانند همین نتیجه را ایجاد کنند.
پاسخ سریع: ابتدا با free -h وضعیت RAM و Swap را بررسی کنید. سپس Kernel Log را برای عبارتهای OOM بخوانید. اگر مشکل داخل Docker رخ داده، مقدار State.OOMKilled و Memory Limit کانتینر را هم بررسی کنید. فقط دیدن Exit Code 137 برای اثبات OOM کافی نیست.
Exit Code 137 دقیقاً یعنی چه؟
در Bash اگر یک Process با Signal شماره N خاتمه پیدا کند، Exit Status معمولاً از رابطه 128 + N به دست میآید. سیگنال SIGKILL شماره ۹ است؛ بنابراین:
128 + 9 = 137
پس Exit Code 137 یعنی برنامه با SIGKILL متوقف شده است. اما هنوز مشخص نیست چه چیزی این Signal را ارسال کرده است.
⚠️ هر Exit Code 137 به معنی OOM نیست. ممکن است Process توسط OOM Killer، Docker Runtime، Timeout یا حتی Kill دستی متوقف شده باشد.
OOM Killer چیست؟
OOM مخفف Out Of Memory است. وقتی Linux نتواند حافظه لازم برای ادامه کار سیستم را تأمین کند، Kernel ممکن است OOM Killer را فعال کند تا با متوقفکردن یک یا چند Process مقداری RAM آزاد شود.
این وضعیت معمولاً در دو حالت دیده میشود:
🔹 OOM در کل سرور: RAM و منابع حافظه سیستم تحت فشار شدید قرار گرفتهاند.
🔹 OOM داخل Container یا cgroup: خود سرور ممکن است RAM آزاد داشته باشد، اما سرویس یا Container به سقف حافظه خودش رسیده باشد.
مرحله ۱: وضعیت RAM و Swap را بررسی کنید
از طریق SSH روی خود سرور این دستور را اجرا کنید:
free -h
بیشتر از ستون available استفاده کنید. صفر بودن مقدار free همیشه به معنی تمامشدن RAM نیست، چون Linux بخشی از حافظه را برای Cache مصرف میکند.
برای بررسی Swap:
swapon --show
اگر خروجی خالی باشد، Swap فعالی روی سرور وجود ندارد.
مرحله ۲: Processهای پرمصرف را پیدا کنید
ps aux --sort=-%mem | head -n 15
اگر یک Process بخش بزرگی از RAM را مصرف میکند یا مصرف آن بهصورت مداوم بالا میرود، احتمال Memory Leak، Worker زیاد یا Cache بیش از حد را بررسی کنید.
برای مشاهده زنده:
top
مرحله ۳: بررسی کنید OOM Killer واقعاً اجرا شده یا نه
روی سرورهای مبتنی بر systemd، Kernel Journal یکی از بهترین منابع تشخیص است:
sudo journalctl -k -b | grep -Ei 'out of memory|oom|killed process'
اگر مشکل در Boot قبلی رخ داده است:
journalctl --list-boots
و برای Boot قبلی:
sudo journalctl -k -b -1 | grep -Ei 'out of memory|oom|killed process'
اگر عبارتهایی مثل Out of memory یا Killed process همراه نام Process دیده شود، شواهد مستقیمتری برای OOM دارید.
مرحله ۴: پیام Killed را بررسی کنید
گاهی برنامه در Shell اجرا میشود و ناگهان فقط این پیام نمایش داده میشود:
Killed
بلافاصله Exit Status را بررسی کنید:
echo $?
اگر خروجی 137 بود، Process با SIGKILL متوقف شده است. حالا باید با Logها مشخص کنید علت SIGKILL چه بوده است.
مرحله ۵: تشخیص Exit Code 137 در Docker
ابتدا Containerهای متوقفشده را ببینید:
docker ps -a
سپس وضعیت Container موردنظر:
docker inspect CONTAINER_NAME --format 'OOMKilled={{.State.OOMKilled}} ExitCode={{.State.ExitCode}} Error={{.State.Error}}'
بهجای CONTAINER_NAME نام واقعی Container را وارد کنید.
اگر خروجی نمونه به این شکل بود:
OOMKilled=true ExitCode=137 Error=
Docker ثبت کرده که Container در وضعیت OOM Kill شده است.
برای اجرای Docker چه منابعی نیاز دارید؟
اگر چند Container، دیتابیس، Worker یا سرویس پردازشی روی یک VPS اجرا میکنید، مجموع مصرف واقعی RAM و محدودیتهای حافظه را هنگام انتخاب سرور در نظر بگیرید. کمبود RAM میتواند باعث توقف ناگهانی سرویسها شود.
تماس با پشتیبانی ایرانیکاسرور: 021-91302467
مرحله ۶: Memory Limit کانتینر را بررسی کنید
docker inspect CONTAINER_NAME --format '{{.HostConfig.Memory}}'
خروجی بر حسب بایت است. مقدار صفر معمولاً یعنی Hard Memory Limit از این بخش تعیین نشده است.
برای مشاهده مصرف لحظهای:
docker stats
مرحله ۷: Memory Limit را فقط افزایش ندهید؛ علت را پیدا کنید
اگر Container به سقف Memory خودش میرسد، باید مشخص کنید Limit خیلی پایین است یا خود برنامه بیش از حد حافظه مصرف میکند.
نمونه تعیین Memory Limit در اجرای مستقیم Docker:
docker run --memory=1g IMAGE_NAME
عدد 1g فقط نمونه است. مقدار مناسب باید بر اساس مصرف واقعی برنامه انتخاب شود.
مرحله ۸: OOM Killer را غیرفعال نکنید
در بیشتر سناریوها غیرفعالکردن OOM Killer راهحل مناسبی نیست. اگر یک برنامه بتواند تمام RAM Host را مصرف کند، ممکن است سرویسهای حیاتی سیستم نیز تحت تأثیر قرار بگیرند.
Docker گزینهای با نام زیر دارد:
--oom-kill-disable
اما این گزینه نباید بهعنوان راهحل عمومی مشکل کمبود RAM استفاده شود.
مرحله ۹: آیا Swap میتواند کمک کند؟
Swap میتواند در برابر جهش کوتاه مصرف حافظه کمک کند، ولی جایگزین RAM کافی نیست. اگر برنامه بهطور دائمی بیش از ظرفیت سرور Memory نیاز داشته باشد، استفاده زیاد از Swap میتواند باعث افت شدید Performance شود.
free -h
swapon --show
مرحله ۱۰: Memory Leak را بررسی کنید
اگر مصرف RAM یک Process بعد از Start کم است اما بهمرور رشد میکند و پایین نمیآید، احتمال Memory Leak یا Cache کنترلنشده وجود دارد.
در این حالت فقط اضافهکردن RAM ممکن است مشکل را دیرتر ظاهر کند. تعداد Workerها، Threadها، Queueها، Batch Size، Cacheها و رفتار خود برنامه باید بررسی شود.
مرحله ۱۱: OOM در systemd Service
اگر برنامه با systemd اجرا میشود:
systemctl status SERVICE_NAME --no-pager
و Log سرویس:
journalctl -u SERVICE_NAME -b --no-pager
بعد از آن Kernel Log را نیز بررسی کنید، چون OOM ممکن است فقط در Log کرنل ثبت شده باشد.
تشخیص سریع علت Exit Code 137
| نشانه | نتیجه |
|---|---|
| Exit Code 137 | SIGKILL رخ داده؛ OOM هنوز اثبات نشده است. |
| 137 + OOMKilled=true | در Docker شواهد مستقیم OOM وجود دارد. |
| Kernel Log شامل Out of memory | OOM در Kernel ثبت شده است. |
| 137 بدون OOM Log | Kill دستی، Timeout یا Runtime را بررسی کنید. |
| Host RAM آزاد است ولی Container OOM میشود | احتمال Memory Limit در cgroup یا Container وجود دارد. |
راههای جلوگیری از OOM
🔹 Memory Leak برنامه را رفع کنید.
🔹 تعداد Worker یا Job همزمان را کاهش دهید.
🔹 Batch Size و Bufferها را کوچکتر کنید.
🔹 Memory Limit کانتینر را متناسب با workload تنظیم کنید.
🔹 روی VPS کمرم، استفاده از Swap را بررسی کنید.
🔹 اگر مصرف طبیعی برنامه از ظرفیت سرور بیشتر است، RAM را افزایش دهید.
پرسشهای متداول
آیا Exit Code 137 همیشه به معنی OOM است؟
خیر. Exit Code 137 یعنی Process با SIGKILL شماره ۹ متوقف شده است. برای اثبات OOM باید Kernel Log، وضعیت Docker یا اطلاعات cgroup بررسی شود.
پیام Killed در لینوکس یعنی چه؟
معمولاً Shell اعلام میکند Process با Signal متوقف شده است. اگر Exit Status برابر 137 باشد، SIGKILL رخ داده است.
چطور بفهمیم Docker Container توسط OOM Killer متوقف شده است؟
با docker inspect مقدار State.OOMKilled را بررسی کنید. مقدار true نشان میدهد Docker وضعیت OOM Kill را ثبت کرده است.
چرا Container OOM میشود ولی Host هنوز RAM دارد؟
چون Container میتواند Memory Limit مستقل داشته باشد. رسیدن به این Limit میتواند OOM داخل همان cgroup ایجاد کند.
آیا Swap مشکل Exit Code 137 را حل میکند؟
فقط در برخی سناریوهای کمبود حافظه کمک میکند. اگر مشکل Memory Leak یا SIGKILL غیرمرتبط با OOM باشد، Swap راهحل اصلی نیست.
آیا افزایش RAM همیشه بهترین راهحل است؟
خیر. اگر برنامه Memory Leak دارد یا Workerهای بیش از حد اجرا میشوند، افزایش RAM فقط بروز مشکل را عقب میاندازد.
منابع رسمی
🔹 Bash Reference Manual درباره Exit Status و Signalها
🔹 Linux Kernel درباره Memory Events و OOM در cgroup v2
🔹 Docker Docs درباره محدودیت Memory و OOM
🔹 Docker Events درباره Kill و Exit Code
جمعبندی
اگر برنامه با پیام Killed یا Exit Code 137 متوقف شد، ابتدا OOM را قطعی فرض نکنید. کد 137 فقط SIGKILL را نشان میدهد. RAM، Swap و Kernel Log را بررسی کنید و در Docker مقدار OOMKilled و Memory Limit را کنترل کنید. اگر OOM تأیید شد، علت اصلی مصرف حافظه را برطرف کنید و فقط در صورت نیاز واقعی منابع سرور را افزایش دهید.
هنوز علت OOM یا Exit Code 137 مشخص نیست؟
اگر سرویس یا Container شما مرتب Kill میشود، میتوانید برای بررسی مصرف RAM، Kernel Log، Docker Memory Limit و تنظیمات سرویس درخواست فنی ثبت کنید.
تماس با پشتیبانی ایرانیکاسرور: 021-91302467






دیدگاهها (۰)