دستورات مانیتورینگ لینوکس: CPU، حافظه، I/O و شبکه

راهنمای عملی دستورات مانیتورینگ سرور لینوکس؛ هر ستون top، vmstat، iostat و ss چه می‌گوید و کدام عدد واقعاً نشانهٔ مشکل است.

۷ دقیقه به‌روزرسانی ۱۸ مهر ۱۴۰۵

سرور جواب می‌دهد ولی کند. SSH با تأخیر باز می‌شود، top را می‌زنید و می‌بینید load average روی ۱۴ است، ولی CPU تقریباً بیکار. اینجا اکثر آدم‌ها دنبال پروسهٔ پرمصرف CPU می‌گردند و پیدا نمی‌کنند، چون مشکل جای دیگری است. این متن مرجع کوتاهی است برای کسی که می‌داند دنبال چه می‌گردد و می‌خواهد بداند هر ستون خروجی دقیقاً چه چیزی را اندازه می‌گیرد.

load average چه چیزی را می‌شمارد و چه چیزی را نه

عدد اول uptime میانگین تعداد پروسه‌هایی است که در ۱، ۵ و ۱۵ دقیقهٔ گذشته در صف اجرا یا در حالت انتظار غیرقابل‌وقفه (D state) بوده‌اند. کلمهٔ کلیدی «غیرقابل‌وقفه» است. پروسه‌ای که روی خواندن از دیسک بلاک شده هم در این عدد حساب می‌شود، حتی اگر یک ثانیه CPU نگرفته باشد.

پس load ۱۴ روی سرور ۴ هسته‌ای لزوماً یعنی CPU اشباع نیست. اول تعداد هسته را ببینید:

nproc
grep -c ^processor /proc/cpuinfo

اگر load از تعداد هسته‌ها بیشتر است، حالا باید بفهمید صف از کجا می‌آید. این تفکیک، تمام کار است.

ستون‌های top که واقعاً مهم‌اند

در top کلید 1 را بزنید تا هر هسته جدا نمایش داده شود؛ اگر یک هسته ۱۰۰٪ است و بقیه بیکار، مشکل single-thread است، نه کمبود ظرفیت کلی. کلید c مسیر کامل دستور را نشان می‌دهد و کلید H تردها را باز می‌کند.

سه ستون را نگاه کنید: %wa (iowait)، %si (softirq) و %st (steal). اگر %wa بالای ۲۰ است، CPU قربانی است نه مقصر. اگر %st بالای صفر و پایدار است، هایپروایزر میزبان سهم شما را نمی‌دهد و هیچ تنظیمی داخل ماشین حلش نمی‌کند؛ اینجا باید با ارائه‌دهنده حرف بزنید. روی سرور ابری این عدد معمولاً صفر است و اگر نیست، سریع پیگیری کنید.

ستون RES حافظهٔ فیزیکی واقعی پروسه است و VIRT تقریباً بی‌معنی است؛ پروسه‌های Java و Go صدها مگابایت VIRT نشان می‌دهند بدون آنکه چیزی مصرف کرده باشند. گمراه‌کننده‌ترین ستون top همین است.

حافظه: چرا free تقریباً همیشه کم است

خروجی free -h را ببینید. ستون available معیار درست است، نه free. لینوکس کش صفحه را در حافظه نگه می‌دارد و آن را آزاد اعلام نمی‌کند، چون آزاد نگه‌داشتن حافظه اتلاف است. سروری که free آن ۲۰۰ مگابایت و available آن ۶ گیگابایت است، مشکل حافظه ندارد.

free -h
cat /proc/meminfo | grep -E 'MemAvailable|Dirty|Writeback'

دو مقدار Dirty و Writeback را جدی بگیرید. اگر Dirty به‌طور پایدار بالای چند صد مگابایت می‌ماند، کرنل نمی‌تواند داده را به‌اندازهٔ کافی سریع به دیسک برساند. نتیجه‌اش پروسه‌های زیادی در حالت D و load بالا با CPU بیکار است. اینجا مشکل I/O است و باید سراغ iostat بروید.

OOM killer را از کجا بفهمیم

dmesg -T | grep -i -E 'oom|killed process'
journalctl -k --since "1 hour ago" | grep -i oom

خطی مثل Out of memory: Killed process 2841 (mysqld) یعنی کرنل پروسه را کشته. اگر MySQL بی‌دلیل ری‌استارت می‌شود و در لاگ خودش چیزی نیست، احتمال زیادی همین است. سرویس‌های systemd با Restart=always بلافاصله بالا می‌آیند و شما فقط یک قطعی کوتاه می‌بینید.

I/O: جایی که بیشتر لودهای بالا متولد می‌شوند

ابزار درست iostat از بستهٔ sysstat است، نه top:

iostat -xz 2 5

فلگ -x آمار توسعه‌یافته و -z حذف دیسک‌های بی‌فعالیت می‌دهد. سه ستون تعیین‌کننده‌اند:

  • %util: درصد زمانی که دستگاه مشغول بوده. بالای ۹۰٪ روی دیسک مکانیکی یعنی اشباع. روی NVMe این عدد به‌سختی به ۱۰۰ می‌رسد چون چند صف موازی دارد و %util دیگر معنای قدیمی خود را نمی‌دهد.
  • await: میانگین میلی‌ثانیهٔ انتظار برای هر درخواست، شامل زمان صف. روی SSD زیر ۱ms طبیعی است؛ بالای ۲۰ms یعنی مشکل دارید.
  • aqu-sz: میانگین طول صف. عدد بزرگ با await بزرگ یعنی دستگاه گلوگاه است، نه برنامه.

برای دیدن اینکه کدام پروسه این I/O را می‌سازد، iotop -oPa را اجرا کنید. فلگ -o فقط پروسه‌های فعال، -P به‌جای ترد، -a مقدار تجمعی.

اینجا اشتباه می‌کنند: خیلی‌ها %util بالا را با «دیسک خراب است» ترجمه می‌کنند و سراغ تعویض سخت‌افزار می‌روند، در حالی که یک کوئری بدون ایندکس یا یک بکاپ mysqldump بدون --single-transaction دارد کل دیسک را می‌خورد. نشانه‌اش این است که مشکل ساعت‌های مشخصی از شب تکرار می‌شود. اول الگوی زمانی را ببینید، بعد سخت‌افزار را متهم کنید.

شبکه: ss جای netstat را گرفته است

netstat در توزیع‌های جدید یا نصب نیست یا کند است. از ss استفاده کنید:

ss -s
ss -tulpn
ss -tan state established | awk '{print $4}' | cut -d: -f2 | sort | uniq -c | sort -rn | head

دستور اول خلاصهٔ سوکت‌ها را می‌دهد. اگر timewait به ده‌ها هزار رسیده، اتصال‌ها سریع باز و بسته می‌شوند و باید net.ipv4.tcp_tw_reuse=1 را در نظر بگیرید. اگر SYN-RECV زیاد است، ممکن است هدف SYN flood باشید.

دستور سوم پورت‌های مقصد پرترافیک را می‌شمارد. پورتی با هزاران اتصال ESTABLISHED معمولاً یعنی یک کانکشن‌پول بدون سقف یا یک اسکریپت که اتصال‌ها را نمی‌بندد. برای دیدن پهنای باند واقعی، iftop -nNP یا nload را اجرا کنید؛ vnstat -l هم برای مصرف تجمعی رابط کار می‌کند.

یک اسکریپت کوتاه برای ثبت لحظه‌ای وضعیت

وقتی سرور کند می‌شود، شما آن لحظه آنلاین نیستید. یک حلقهٔ ساده بگذارید که هر ۳۰ ثانیه وضعیت را در فایل بریزد:

while true; do
  echo "=== $(date -Is) ===" >> /var/log/snapshot.log
  uptime >> /var/log/snapshot.log
  free -m | head -2 >> /var/log/snapshot.log
  iostat -x 1 2 | tail -20 >> /var/log/snapshot.log
  sleep 30
done

هزینه‌اش این است که خودش کمی I/O تولید می‌کند و روی دیسک‌های کوچک باید مراقب رشد فایل باشید. اما وقتی مشکل بعد از دو روز برگشت، این فایل تنها شاهد شماست. اگر ترجیح می‌دهید به‌جای اسکریپت دستی از ابزار آماده استفاده کنید، راهنمای تشخیص علت لود بالای سرور مسیر گام‌به‌گام را پوشش می‌دهد.

کدام ابزار را برای چه کاری برداریم

نیازابزارنکته
نمای کلی لحظه‌ایtop / htophtop تفکیک ترد و درخت پروسه دارد
صف و iowaitvmstat 1ستون b تعداد پروسه‌های بلاک‌شده است
دیسکiostat -xz 2await مهم‌تر از %util روی NVMe
شبکهss -s، iftopnetstat را کنار بگذارید
تاریخچهsar -u -r -d 1 3نیازمند فعال‌بودن sysstat

اگر sysstat را فعال کنید، sar می‌تواند وضعیت دیروز را هم نشان دهد. این تنها راه دیدن گذشته است، چون top فقط حال را می‌بیند. فعال‌سازی‌اش یک خط است:

sed -i 's/^ENABLED=.*/ENABLED="true"/' /etc/default/sysstat
systemctl enable --now sysstat

یک تذکر دربارهٔ vmstat: ستون r تعداد پروسه‌های در صف اجرا و b تعداد پروسه‌های بلاک‌شده است. اگر r بزرگ است، CPU گلوگاه است. اگر b بزرگ است، دیسک. همین یک تفکیک، نیمی از تشخیص را حل می‌کند.

برای سرورهایی که کار سنگین دارند و می‌خواهید I/O را از ابتدا درست بچینید، سرور اختصاصی با دیسک NVMe تفاوت await را از ده‌ها میلی‌ثانیه به زیر یک میلی‌ثانیه می‌آورد و همان کوئری سنگین دیگر کل ماشین را زمین نمی‌زند. اگر روی هاست لینوکس هستید و ابزارها را نصب نمی‌کنید چون دسترسی root ندارید، از پشتیبانی بخواهید sysstat و iotop را نصب کند؛ بدون این دو، عیب‌یابی تقریباً حدس‌وگمان است.

قدم بعدی مشخص است: همین حالا iostat -xz 2 5 را روی سرور بزنید و await را یادداشت کنید. اگر بالای ۲۰ms بود، قبل از هر کار دیگری سراغ iotop -oPa بروید. عدد پایه‌ای که امروز ثبت می‌کنید، فردا که سرور کند شد تنها مرجع مقایسهٔ شماست.

پرسش‌های پرتکرار

load average چند طبیعی است؟

معیار درست نسبت load به تعداد هسته‌هاست، نه خود عدد. روی سرور ۴ هسته‌ای، load زیر ۴ یعنی صف مدیریت‌شده است و بالای ۸ یعنی چیزی اشباع شده. اما اگر %wa بالا باشد، load بالا از دیسک می‌آید و افزودن CPU هیچ کمکی نمی‌کند.

چرا free تقریباً همیشه حافظهٔ کمی نشان می‌دهد؟

چون لینوکس حافظهٔ آزاد را برای کش صفحه خرج می‌کند و آن را در ستون free نمی‌شمارد. ستون available تخمین درستی از حافظهٔ قابل استفاده می‌دهد. اگر available زیر ۱۰٪ کل حافظه است و swap هم پر می‌شود، آن‌وقت مشکل واقعی دارید.

تفاوت %util و await در iostat چیست؟

%util می‌گوید دیسک چند درصد زمان مشغول بوده و await می‌گوید هر درخواست به‌طور میانگین چند میلی‌ثانیه طول کشیده، شامل زمان انتظار در صف. روی NVMe که چند صف موازی دارد، %util می‌تواند پایین بماند در حالی که await بالا رفته؛ پس await معیار قابل‌اعتمادتری است.

چطور بفهمم کدام پروسه باعث ترافیک شبکه است؟

ss -tunp پروسهٔ صاحب هر سوکت را نشان می‌دهد و iftop -nNP پهنای باند هر اتصال را زنده نمایش می‌دهد. برای مصرف تجمعی هر رابط، vnstat -l کافی است. اگر پورتی هزاران اتصال ESTABLISHED دارد، اول همان را بررسی کنید.

آیا این مطلب برایتان مفید بود؟