مانیتورینگ سرور لینوکس یعنی پاییدن مداوم چند عدد کلیدی (CPU، load average، حافظه و swap، فضای دیسک، I/O دیسک، شبکه و سالم بودن سرویس‌ها) تا پیش از اینکه کاربر بگوید «سایت کند شده» یا «بالا نمی‌آید»، خودتان بدانید. برای یک نگاه سریع، همین ابزارهای داخلی کافی‌اند: uptime برای load، free -h برای حافظه، df -h برای دیسک، vmstat 1 و iostat -x 1 برای CPU و I/O، و htop برای دیدن اینکه کدام پروسس مقصر است.

ولی مانیتورینگ واقعی دو چیز دیگر هم لازم دارد: تاریخچه (تا بدانید دیروز ساعت ۳ چه شد) و هشدار (تا لازم نباشد مدام نگاه کنید). برای این دو، یک داشبورد سبک مثل Netdata، یک بررسی uptime از بیرون سرور و یک اسکریپت سلامت کوچک که cron اجرایش کند، برای بیشتر سرورهای کوچک و متوسط کافی است. در ادامه هر عدد را معنی می‌کنیم، ابزارها را مقایسه می‌کنیم و آن اسکریپت را می‌نویسیم. مثال‌ها برای Ubuntu 24.04 است.

چه چیزی را باید پایید؟

CPU

bash
vmstat 1 5

در خروجی vmstat ستون‌های بخش cpu مهم‌اند:

  • us: زمان صرف‌شده برای برنامه‌ها. اگر بالاست، برنامه یا پایگاه‌داده واقعاً کار محاسباتی می‌کند.
  • sy: زمان کرنل.
  • wa (iowait): CPU بیکار است چون منتظر دیسک است. wa بالا یعنی گلوگاه دیسک است، نه پردازنده.
  • st (steal): روی سرور مجازی، زمانی که میزبان CPU را به ماشین‌های دیگر داده. اگر مدام بالاست، مشکل از سرور شما نیست و از سرویس‌دهنده است.

load average چیست؟

bash
uptime
nproc

سه عدد آخر uptime میانگین load در ۱، ۵ و ۱۵ دقیقه‌ی اخیر است. load یعنی تعداد پروسس‌هایی که یا در حال اجرا هستند یا منتظر CPU‌اند؛ در لینوکس پروسس‌هایی که منتظر دیسک‌اند (حالت D) هم شمرده می‌شوند.

این عدد را باید با تعداد هسته‌ها (nproc) مقایسه کرد. روی سرور ۴ هسته‌ای، load برابر ۴ یعنی همه‌ی هسته‌ها مشغول‌اند و صفی تشکیل نشده؛ load برابر ۱۲ یعنی به‌طور میانگین هشت پروسس منتظر نوبت‌اند. مقایسه‌ی سه عدد هم روند را نشان می‌دهد: اگر عدد ۱ دقیقه خیلی بیشتر از ۱۵ دقیقه است، مشکل همین حالا شروع شده.

load بالا با CPU پایین معمولاً یعنی پروسس‌ها پشت دیسک گیر کرده‌اند؛ سراغ iostat بروید.

حافظه و swap

bash
free -h

به ستون available نگاه کنید، نه free. لینوکس RAM خالی را برای کش دیسک استفاده می‌کند و free پایین طبیعی است. نشانه‌ی واقعی کمبود حافظه این‌هاست:

  • available مدام نزدیک صفر است.
  • در vmstat 1 ستون‌های si و so (ورود و خروج از swap) مدام غیرصفرند. کمی swap مصرف‌شده مشکلی نیست؛ جابه‌جایی مداوم مشکل است.
  • OOM killer پروسسی را کشته:
bash
journalctl -k | grep -i "out of memory"

دیسک: فضا و I/O

df -h فضا و df -i تعداد inode را نشان می‌دهد. اگر دیسک پر شده، مراحل کامل را در دیسک سرور لینوکس پر شده؛ قدم‌به‌قدم چه کنیم؟ نوشته‌ایم.

پر بودن تنها مشکل دیسک نیست؛ کند بودنش هم هست:

bash
sudo apt install sysstat
iostat -x 1

ستون %util نزدیک ۱۰۰ یعنی دیسک تمام وقت مشغول است، و r_await و w_await میانگین زمان انتظار هر درخواست خواندن و نوشتن (به میلی‌ثانیه) را نشان می‌دهند. اگر این اعداد بالا رفته‌اند، با sudo iotop (بسته‌ی iotop) ببینید کدام پروسس این‌قدر می‌خواند یا می‌نویسد.

شبکه

bash
ss -s              # خلاصه‌ی اتصال‌ها
ss -tulpn          # چه چیزی روی کدام پورت گوش می‌دهد
ip -s link         # بایت‌ها، خطاها و بسته‌های دورریخته‌ی هر کارت شبکه

تعداد زیاد اتصال در حالت TIME-WAIT یا رشد ناگهانی اتصال‌ها می‌تواند نشانه‌ی ترافیک غیرعادی یا برنامه‌ای باشد که اتصال‌ها را درست نمی‌بندد.

سلامت سرویس‌ها

عددهای سیستم ممکن است همه خوب باشند و سایت باز هم خراب باشد:

bash
systemctl --failed
curl -sS -o /dev/null -w '%{http_code} %{time_total}s\n' https://example.com/

اگر برنامه‌تان یک آدرس سلامت (مثلاً /up در لاراول) دارد، همان را بررسی کنید؛ چون علاوه بر وب‌سرور، اتصال به پایگاه‌داده را هم می‌سنجد. ساختن سرویس‌هایی که systemd مراقبشان باشد را در ساخت سرویس systemd توضیح داده‌ایم.

ابزارها: از دستورهای داخلی تا داشبورد

ابزارهای داخلی و htop

uptime، free، vmstat، df و ss روی هر سروری هستند. htop همه را در یک صفحه‌ی زنده جمع می‌کند و با F6 می‌شود پروسس‌ها را بر اساس CPU یا حافظه مرتب کرد. ضعف همه‌ی این‌ها یکی است: فقط «همین حالا» را نشان می‌دهند. دستورهای پایه‌تر را در دستورهای ضروری لینوکس برای مدیریت سرور ببینید.

sar: تاریخچه بدون داشبورد

بسته‌ی sysstat علاوه بر iostat ابزار sar را دارد که هر چند دقیقه آمار سیستم را ذخیره می‌کند. در اوبونتو باید جمع‌آوری را روشن کنید:

bash
sudo sed -i 's/^ENABLED="false"/ENABLED="true"/' /etc/default/sysstat
sudo systemctl enable --now sysstat

بعد از چند ساعت، sar -u مصرف CPU، sar -r حافظه و sar -q load امروز را نشان می‌دهد. برای روزهای قبل: sar -u -f /var/log/sysstat/saDD که DD روز ماه است.

Netdata: داشبورد سبک و آماده

Netdata یک داشبورد وب است که بدون تنظیم، صدها نمودار از CPU، حافظه، دیسک، شبکه و سرویس‌های شناخته‌شده (nginx، MySQL، Redis و…) با دقت ثانیه‌ای می‌سازد و هشدارهای پیش‌فرض هم دارد.

bash
sudo apt install netdata

داشبورد روی پورت 19999 بالا می‌آید. این پورت را برای همه باز نکنید؛ اگر لازم است از بیرون ببینید، با ufw فقط برای IP خودتان باز کنید:

bash
sudo ufw allow from 203.0.113.10 to any port 19999 proto tcp

(203.0.113.10 را با IP خودتان عوض کنید.) نسخه‌ی مخزن اوبونتو ممکن است از نسخه‌ی سایت Netdata قدیمی‌تر باشد؛ برای نسخه‌ی تازه، روش نصب مستندات Netdata را دنبال کنید. Netdata خودش هم مقداری RAM و CPU مصرف می‌کند؛ روی سرورهای خیلی کوچک این را در نظر بگیرید.

Prometheus و Grafana

ترکیب Prometheus (جمع‌آوری و ذخیره‌ی متریک‌ها)، node_exporter (متریک‌های هر سرور) و Grafana (داشبورد) استاندارد صنعت برای چندین سرور و سرویس است. قدرتمند و منعطف است، ولی راه‌اندازی و نگه‌داری‌اش کار واقعی است و برای یک سرور تنها معمولاً زیادی است.

بررسی از بیرون سرور

هر ابزاری که روی خود سرور اجرا شود، وقتی سرور کلاً از دسترس خارج شود ساکت می‌ماند. برای همین دست‌کم یک بررسی باید از جای دیگری انجام شود: یک سرویس uptime monitoring آنلاین که هر چند دقیقه آدرس سایت را باز می‌کند و اگر جواب نگرفت خبر می‌دهد، یا ابزار متن‌بازی مثل Uptime Kuma روی یک سرور دیگر.

مقایسه

ابزار چه نشان می‌دهد تاریخچه هشدار زحمت راه‌اندازی مناسب برای
uptime، free، vmstat، df وضعیت لحظه‌ای ندارد ندارد هیچ عیب‌یابی همین حالا
htop و iotop پروسس‌های پرمصرف ندارد ندارد نصب یک بسته پیدا کردن مقصر
sar (sysstat) CPU، حافظه، I/O، شبکه دارد (فایل روزانه) ندارد کم «دیشب چه شد؟»
Netdata صدها متریک با نمودار دارد دارد کم یک تا چند سرور
Prometheus + Grafana هر متریکی، چند سرور دارد دارد (Alertmanager) زیاد چندین سرور و تیم
بررسی uptime از بیرون در دسترس بودن سایت بسته به ابزار دارد کم هر سایتی، بدون استثنا
اسکریپت سلامت با cron همان چیزی که می‌نویسید در journal دارد کم شروع ساده و سفارشی

یک اسکریپت سلامت کوچک با cron

این اسکریپت دیسک، حافظه، load، چند سرویس و یک آدرس سلامت را بررسی می‌کند و فقط وقتی وضعیت تغییر کند پیام می‌دهد، تا هر پنج دقیقه یک هشدار تکراری نگیرید:

/usr/local/bin/health-check.sh
#!/usr/bin/env bash
set -uo pipefail

DISK_LIMIT=85          # درصد
MEM_MIN_AVAIL=10       # درصد
SERVICES=(nginx php8.3-fpm mysql)
URL="https://example.com/up"
WEBHOOK_URL="${WEBHOOK_URL:-}"
STATE=/var/tmp/health-check.last

problems=()

# فضای دیسک
while read -r use mount; do
  use=${use%\%}
  (( use >= DISK_LIMIT )) && problems+=("disk $mount ${use}%")
done < <(df -P -x tmpfs -x devtmpfs -x squashfs -x overlay | awk 'NR>1 {print $5, $6}')

# حافظه‌ی در دسترس
mem=$(awk '/^MemTotal/ {t=$2} /^MemAvailable/ {a=$2} END {printf "%d", a*100/t}' /proc/meminfo)
(( mem < MEM_MIN_AVAIL )) && problems+=("memory available ${mem}%")

# load بیشتر از دو برابر هسته‌ها
load=$(cut -d' ' -f1 /proc/loadavg)
cores=$(nproc)
awk -v l="$load" -v c="$cores" 'BEGIN {exit !(l > c * 2)}' && problems+=("load $load on $cores cores")

# سرویس‌ها
for s in "${SERVICES[@]}"; do
  systemctl is-active --quiet "$s" || problems+=("service $s down")
done

# آدرس سلامت
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$URL")
[[ $code == 200 ]] || problems+=("$URL returned $code")

if (( ${#problems[@]} )); then
  msg="[$(hostname)] $(printf '%s; ' "${problems[@]}")"
else
  msg="[$(hostname)] OK"
fi

last=$(cat "$STATE" 2>/dev/null || true)
if [[ $msg != "$last" ]]; then
  printf '%s\n' "$msg" > "$STATE"
  logger -t health-check "$msg"
  if [[ -n $WEBHOOK_URL ]]; then
    curl -s --max-time 10 -H 'Content-Type: application/json' \
      -d "{\"text\": \"$msg\"}" "$WEBHOOK_URL" > /dev/null || true
  fi
fi
bash
sudo chmod +x /usr/local/bin/health-check.sh
sudo /usr/local/bin/health-check.sh && journalctl -t health-check -n 5

و اجرای خودکار هر پنج دقیقه:

/etc/cron.d/health-check
WEBHOOK_URL=https://hooks.example.com/your-webhook
*/5 * * * * root /usr/local/bin/health-check.sh

WEBHOOK_URL را با آدرس وب‌هوک پیام‌رسان یا سرویسی که استفاده می‌کنید عوض کنید؛ بدون آن، پیام‌ها فقط در journal ثبت می‌شوند. فهرست سرویس‌ها و آستانه‌ها را با سرور خودتان تطبیق دهید. نکته‌های کرون، مثل محیط محدود و جلوگیری از اجرای هم‌زمان، را در کرون جاب در لینوکس آورده‌ایم.

یادتان باشد این اسکریپت جای بررسی از بیرون را نمی‌گیرد: اگر سرور خاموش شود، اسکریپت هم اجرا نمی‌شود.

از کجا شروع کنیم؟

  • امروز: یک بررسی uptime از بیرون برای سایت بگذارید.
  • همین هفته: اسکریپت سلامت بالا را با آستانه‌های خودتان در cron قرار دهید و sysstat را روشن کنید.
  • اگر بیشتر خواستید: Netdata را نصب کنید تا نمودار و هشدار آماده داشته باشید.
  • وقتی چند سرور شدید: به Prometheus و Grafana فکر کنید.

و مانیتورینگ را با نسخه‌ی پشتیبان اشتباه نگیرید؛ مانیتورینگ می‌گوید چیزی خراب شده، بکاپ است که آن را برمی‌گرداند. اگر سرور تازه است، اول ساعت اول یک سرور لینوکس تازه را انجام دهید.

جمع‌بندی

مانیتورینگ سرور لینوکس با چند سؤال ساده شروع می‌شود: CPU و load نسبت به تعداد هسته‌ها چطور است، available حافظه چقدر است و swap جابه‌جا می‌شود یا نه، دیسک چقدر پر و چقدر مشغول است، و سرویس‌ها و آدرس سلامت جواب می‌دهند یا نه. ابزارهای داخلی برای «همین حالا» کافی‌اند، sar و Netdata تاریخچه می‌دهند، و یک اسکریپت کوچک با cron به‌اضافه‌ی یک بررسی از بیرون، هشدار را به دستتان می‌رساند. از ساده شروع کنید و فقط وقتی نیاز واقعی دیدید سراغ ابزارهای سنگین‌تر بروید.