0Pricing
Linux Command Line & Bash Scripting Mastery · درس

إنشاء سكربتات فحص صحة النظام والتنبيه

اجمع مقاييس الحمل والذاكرة والقرص وأطلق تنبيهات قائمة على الحدود من خلال سكربتات مجدولة

إنشاء سكربتات فحص صحة النظام والتنبيه درس مجاني في Linux Command Line & Bash Scripting Mastery على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Linux Command Line & Bash Scripting Mastery، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Linux Command Line & Bash Scripting Mastery 4 دروس في المجموع.

أهمية فحوصات سلامة النظام

قد تتدهور خوادم الإنتاج دون أن يُلاحظ ذلك. فتسبب ارتفاعات استخدام CPU وتسربات الذاكرة وامتلاء الأقراص انقطاعات، ولكن فقط إذا لم يلاحظها أحد في الوقت المناسب. تعمل نصوص فحص سلامة النظام على أتمتة حلقة المراقبة: جمع المقاييس، ومقارنتها بالحدود، وإطلاق التنبيهات قبل أن يشعر المستخدمون بالمشكلة.

  • تُجدول عبر cron، فتعمل كل بضع دقائق دون تدخل بشري
  • تنتج مخرجات متسقة ومؤرخة زمنيًا، مناسبة لتجميع السجلات
  • تحافظ المنطقية القائمة على الحدود على فائدة التنبيهات — فلا يؤدي كل اضطراب بسيط إلى تنبيه فريق المناوبة

في هذا الدرس ستنشئ نص فحص سلامة بمستوى الإنتاج من الصفر، طبقةً تلو الأخرى، لتغطية متوسط الحمل وضغط الذاكرة واستخدام القرص.

التقاط متوسط الحمل

يعرض Linux متوسطات الحمل لمدة دقيقة واحدة و5 دقائق و15 دقيقة عبر /proc/loadavg والأمر uptime. وبالنسبة إلى النصوص البرمجية، يُعدّ /proc/loadavg المصدر الأنظف — فلا توجد مشكلات متعلقة باللغة أو اختلافات في التحليل بين التوزيعات.

يقرأ المقطع أدناه متوسط الحمل لمدة دقيقة واحدة ويخزنه في متغير لمقارنته بحد معين. يستخرج cut الحقل الأول، بينما يزيل awk الجزء العشري لإجراء مقارنة صحيحة باستخدام bc للحساب بالفاصلة العائمة.

#!/usr/bin/env bash
# Read 1-minute load average from /proc/loadavg
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
echo "Raw load average: $LOAD_RAW"

# Number of CPU cores — used to normalise load
CPU_CORES=$(nproc)
echo "CPU cores: $CPU_CORES"

# Compute load percentage (load / cores * 100) using bc
LOAD_PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)
echo "Load %: $LOAD_PCT"

مقارنة الحدود بالقيم ذات الفاصلة العائمة

لا يستطيع Bash مقارنة الأعداد ذات الفاصلة العائمة بشكل أصلي — إذ يتسبب [ 1.5 -gt 1.2 ] في خطأ. والحلان الاصطلاحيان هما:

  • bc — يُخرج 1 (صحيح) أو 0 (خطأ) من تعبير المقارنة
  • awk — يمكنه تقييم شروط الأعداد العشرية ضمن سلسلة أوامر

يُبقي استخدام bc المنطق واضحًا وسهل الاختبار. ويُرجع النمط $(echo "$A > $B" | bc) القيمة 1 عند تحقق الشرط، ويمكنك اختبار ذلك باستخدام [ ... -eq 1 ].

#!/usr/bin/env bash
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
CPU_CORES=$(nproc)
THRESHOLD=80  # alert when load % exceeds 80%

LOAD_PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)

# bc returns 1 if the expression is true
if [ "$(echo "$LOAD_PCT > $THRESHOLD" | bc)" -eq 1 ]; then
    echo "ALERT: Load is ${LOAD_PCT}% (threshold ${THRESHOLD}%)"
else
    echo "OK: Load is ${LOAD_PCT}%"
fi

جمع مقاييس الذاكرة

يُعدّ /proc/meminfo المصدر المعتمد لإحصاءات الذاكرة في Linux. ومن الحقول المهمة:

  • MemTotal — إجمالي ذاكرة RAM الفعلية بالكيلوبايت
  • MemAvailable — الكيلوبايتات المقدّرة المتاحة للتخصيصات الجديدة دون استخدام التبديل (وهو أفضل من MemFree)

يُعدّ استخدام awk مع مطابقة نمط الطريقة الأنظف لاستخراج هذه القيم. ويؤدي تقسيم MemAvailable على MemTotal ثم طرح الناتج من 100 إلى حساب النسبة المئوية للذاكرة المستخدمة، التي تحدد حد التنبيه.

#!/usr/bin/env bash
# Extract memory figures from /proc/meminfo (values in kB)
MEM_TOTAL=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)
MEM_AVAIL=$(awk '/^MemAvailable:/ {print $2}' /proc/meminfo)

# Used memory percentage
MEM_USED_PCT=$(echo "scale=2; (1 - $MEM_AVAIL / $MEM_TOTAL) * 100" | bc)

echo "Total RAM : ${MEM_TOTAL} kB"
echo "Available : ${MEM_AVAIL} kB"
echo "Used      : ${MEM_USED_PCT}%"

جمع مقاييس استخدام القرص

يعرض الأمر df استخدام نظام الملفات. وبالنسبة إلى النصوص البرمجية، هناك خياران أساسيان:

  • -h — أحجام مقروءة للبشر (للعرض فقط؛ تجنب استخدامها في العمليات الحسابية)
  • --output=pcent,target — أعمدة قابلة للتحليل آليًا (GNU coreutils)

يتيح التكرار على جميع أنظمة الملفات المحمّلة للنص البرمجي تحديد أي قسم ممتلئ بشكل حرج، وليس / فقط. وتُزال العلامة % باستخدام tr -d '%' قبل المقارنة الصحيحة.

#!/usr/bin/env bash
DISK_THRESHOLD=85

# Skip header line with tail -n +2
# --output=pcent,target gives "85% /var" style lines
df --output=pcent,target | tail -n +2 | while read -r USED_PCT MOUNT; do
    # Remove the % sign for arithmetic
    USED_INT=${USED_PCT//%/}

    if [ "$USED_INT" -ge "$DISK_THRESHOLD" ]; then
        echo "ALERT: Disk $MOUNT is ${USED_PCT} full"
    else
        echo "OK   : Disk $MOUNT is ${USED_PCT} full"
    fi
done

مخرجات تنبيهات منظمة مع طوابع زمنية

تكاد تكون رسائل التنبيه التي لا تحتوي على طوابع زمنية عديمة الفائدة في ملفات السجل أو تقارير البريد الإلكتروني. وتسهّل بادئة متسقة تحليل السجلات باستخدام grep أو وكلاء إرسال السجلات.

عرّف دالة تنبيه صغيرة في أعلى النص البرمجي. فهي تضيف في البداية طابعًا زمنيًا بتنسيق ISO-8601، ومستوى الخطورة، واسم الفحص. وتكتب جميع التنبيهات إلى كل من stdout وملف سجل عبر tee.

  • date -u +"%Y-%m-%dT%H:%M:%SZ" — طابع زمني بتوقيت UTC مستقل عن اللغة
  • تؤدي الكتابة إلى stderr لتنبيهات ALERT وإلى stdout لحالات OK إلى فصل الإشارات المهمة عن الضوضاء في سلاسل الأوامر
#!/usr/bin/env bash
LOG_FILE="/var/log/healthcheck.log"

alert() {
    local LEVEL="$1"   # OK | WARN | ALERT
    local CHECK="$2"
    local MSG="$3"
    local TS
    TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    local LINE="[$TS] [$LEVEL] [$CHECK] $MSG"

    if [ "$LEVEL" = "ALERT" ]; then
        echo "$LINE" | tee -a "$LOG_FILE" >&2
    else
        echo "$LINE" | tee -a "$LOG_FILE"
    fi
}

# Usage examples
alert "OK"    "DISK"  "/ is 42% full"
alert "ALERT" "DISK"  "/var is 91% full"

إرسال تنبيهات البريد الإلكتروني باستخدام mail وsendmail

أبسط آلية للتنبيه على الخادم هي البريد الإلكتروني عبر وكيل نقل البريد المحلي (postfix أو sendmail أو msmtp). ويؤلف الأمر mail (من mailutils أو bsd-mailx) رسالةً ويرسلها في سطر واحد.

  • -s — سطر الموضوع
  • مرّر نص الرسالة عبر stdin
  • على الخوادم التي لا تحتوي على وكيل نقل بريد محلي، استبدل mail باستدعاء curl إلى واجهة برمجة تطبيقات للبريد الإلكتروني المعاملاتي

احمِ عملية الإرسال باستخدام قفل لإزالة التكرار حتى لا تؤدي حالة صاخبة واحدة إلى إغراق صندوق الوارد.

#!/usr/bin/env bash
ALERT_EMAIL="ops@example.com"
LOCK_DIR="/tmp/healthcheck_locks"
mkdir -p "$LOCK_DIR"

send_alert() {
    local CHECK="$1"
    local MSG="$2"
    local LOCK="$LOCK_DIR/${CHECK}.lock"

    # Only send if no lock exists (prevents repeated emails within the hour)
    if [ ! -f "$LOCK" ]; then
        echo "$MSG" | mail -s "[ALERT] $CHECK on $(hostname)" "$ALERT_EMAIL"
        touch "$LOCK"
        # Lock expires after 1 hour via cron or find+delete
        echo "Alert sent for $CHECK"
    else
        echo "Alert suppressed for $CHECK (lock active)"
    fi
}

send_alert "HIGH_LOAD" "Load average exceeded 80% on $(hostname) at $(date)"

تركيب سكربت فحص الحالة الصحية الكامل

الآن ادمج عمليات الفحص الثلاث — الحمل والذاكرة والقرص — في سكربت واحد متماسك، مع وضع الحدود القابلة للتهيئة في الأعلى. هذا هو النمط المستخدم في أتمتة إدارة الأنظمة في بيئات الإنتاج:

  • التصريح بالثوابت في الأعلى لتسهيل ضبطها دون تعديل المنطق
  • عزل كل عملية فحص داخل دالة لتحسين قابلية القراءة والاختبار الوحدي
  • تتولى دالة main تنسيق الاستدعاءات
  • رمز الخروج 1 إذا أطلق أي تنبيه، و0 خلاف ذلك — مما يجعل السكربت قابلاً للدمج مع أطر المراقبة مثل Nagios/Icinga
#!/usr/bin/env bash
set -euo pipefail

# ── Thresholds ───────────────────────────────────────────
LOAD_THRESHOLD=80   # percent of CPU capacity
MEM_THRESHOLD=90    # percent used
DISK_THRESHOLD=85   # percent used
ALERT_EMAIL="ops@example.com"
LOG_FILE="/var/log/healthcheck.log"
ALERT_FIRED=0

# ── Helpers ──────────────────────────────────────────────
ts()    { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
log()   { echo "[$(ts)] $*" | tee -a "$LOG_FILE"; }
alert() { log "ALERT: $*"; echo "$*" | mail -s "[ALERT] $(hostname)" "$ALERT_EMAIL" 2>/dev/null; ALERT_FIRED=1; }

# ── Checks ───────────────────────────────────────────────
check_load() {
    local raw cores pct
    raw=$(cut -d' ' -f1 /proc/loadavg)
    cores=$(nproc)
    pct=$(echo "scale=2; $raw / $cores * 100" | bc)
    if [ "$(echo "$pct > $LOAD_THRESHOLD" | bc)" -eq 1 ]; then
        alert "Load ${pct}% exceeds ${LOAD_THRESHOLD}%"
    else
        log "OK load=${pct}%"
    fi
}

check_memory() {
    local total avail pct
    total=$(awk '/^MemTotal:/    {print $2}' /proc/meminfo)
    avail=$(awk '/^MemAvailable:/{print $2}' /proc/meminfo)
    pct=$(echo "scale=2; (1 - $avail / $total) * 100" | bc)
    if [ "$(echo "$pct > $MEM_THRESHOLD" | bc)" -eq 1 ]; then
        alert "Memory ${pct}% used (threshold ${MEM_THRESHOLD}%)"
    else
        log "OK memory=${pct}%"
    fi
}

check_disk() {
    df --output=pcent,target | tail -n +2 | while read -r used mnt; do
        local pct_int=${used//%/}
        if [ "$pct_int" -ge "$DISK_THRESHOLD" ]; then
            alert "Disk $mnt at ${used}"
        else
            log "OK disk $mnt=${used}"
        fi
    done
}

main() {
    log "=== Health check START ==="
    check_load
    check_memory
    check_disk
    log "=== Health check END (alerts=$ALERT_FIRED) ==="
    exit "$ALERT_FIRED"
}

main

الجدولة باستخدام Cron

لا يحقق سكربت فحص الحالة الصحية قيمة فعلية إلا عند تشغيله تلقائياً. يُعد cron أداة الجدولة القياسية في Unix. حرّر crontab على مستوى النظام أو ملفاً مخصصاً داخل /etc/cron.d/ لجدولة تشغيل السكربت.

  • التشغيل كل 5 دقائق: */5 * * * *
  • استخدم دائماً مسارات مطلقة في cron — إذ تكون قيمة $PATH محدودة في بيئة cron
  • أعد توجيه المخرجات لمنع cron من إرسال رسالة بريد في كل تشغيل: >> /var/log/healthcheck.log 2>&1
  • استخدم MAILTO="" في أعلى crontab لإيقاف رسائل البريد التي يرسلها cron نفسه
# /etc/cron.d/healthcheck
# Run the health check every 5 minutes as root
MAILTO=""
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

*/5 * * * * root /usr/local/sbin/healthcheck.sh >> /var/log/healthcheck.log 2>&1

منع عواصف التنبيهات باستخدام أقفال فترة التهدئة

عندما يستمر تجاوز حد معين، يطلق السكربت البسيط تنبيهاً كل 5 دقائق — أي عشرات الرسائل قبل أن يتمكن المهندس من الاستجابة. يعمل قفل فترة التهدئة على منع التنبيهات المتكررة خلال فترة قابلة للتهيئة.

النمط المتبع هو: كتابة ملف قفل عند إطلاق أول تنبيه؛ وتخطي التنبيهات اللاحقة ما دام الملف أحدث من فترة التهدئة؛ واستخدام find مع -mmin للتحقق من عمر الملف بشكل ذري دون إجراء حسابات على التواريخ.

#!/usr/bin/env bash
LOCK_DIR="/tmp/hc_locks"
COOLDOWN_MIN=60  # suppress repeat alerts for 60 minutes
mkdir -p "$LOCK_DIR"

should_alert() {
    local check="$1"
    local lock="$LOCK_DIR/${check}.lock"

    if [ ! -f "$lock" ]; then
        # No lock — allow alert and create lock
        touch "$lock"
        return 0  # true: send alert
    fi

    # Lock exists — check if it is older than the cooldown
    # find returns the filename only if it's OLDER than COOLDOWN_MIN
    local expired
    expired=$(find "$lock" -mmin +"$COOLDOWN_MIN" 2>/dev/null)

    if [ -n "$expired" ]; then
        touch "$lock"  # refresh lock timestamp
        return 0       # cooldown expired — allow alert
    fi

    return 1  # still within cooldown — suppress
}

# Usage
if should_alert "HIGH_LOAD"; then
    echo "Sending load alert..."
    # mail -s "..." ops@example.com <<< "Load too high"
else
    echo "Load alert suppressed (cooldown active)"
fi

اختبار سكربت فحص الحالة الصحية والتحقق منه

قبل النشر، تحقّق من السكربت بثلاث طرق:

  • فحص الصياغة: يكتشف bash -n healthcheck.sh أخطاء التحليل دون تنفيذ السكربت
  • وضع التتبع: يطبع bash -x healthcheck.sh كل أمر أثناء تنفيذه — وهو مفيد جداً لتصحيح الأخطاء
  • تجاوز الحدود: خفّض الحدود مؤقتاً إلى قيم قريبة من الصفر لكي يطلق السكربت تنبيهات على مضيف سليم، وبذلك تتأكد من عمل مسار التنبيه من البداية إلى النهاية

ولاختبار مسار البريد الإلكتروني، أعد توجيه mail إلى ملف سجل أثناء الاختبار باستخدام علامة MOCK_MAIL:

#!/usr/bin/env bash
# Smoke-test the alert path without sending real email
MOCK_MAIL=true
ALERT_EMAIL="ops@example.com"

send_mail() {
    local subject="$1"
    local body="$2"
    if [ "$MOCK_MAIL" = true ]; then
        echo "[MOCK MAIL] To: $ALERT_EMAIL | Subject: $subject"
        echo "[MOCK MAIL] Body: $body"
    else
        echo "$body" | mail -s "$subject" "$ALERT_EMAIL"
    fi
}

# Override threshold to guarantee an alert fires
LOAD_THRESHOLD=0   # Any load will exceed 0%
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
CPU_CORES=$(nproc)
PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)

if [ "$(echo "$PCT > $LOAD_THRESHOLD" | bc)" -eq 1 ]; then
    send_mail "[ALERT] Load on $(hostname)" "Load is ${PCT}%"
fi

اختبار المعرفة: استراتيجية فترة التهدئة

تأمل السيناريو التالي: تعمل مهمة cron لفحص الحالة الصحية كل 5 دقائق. يتجاوز استخدام القرص على /var نسبة 85% ويظل كذلك لمدة 3 ساعات. تريد أن يتلقى المهندس المناوب تنبيهاً مرة واحدة كل ساعة، وليس كل 5 دقائق. ما استراتيجية التنفيذ الأنسب؟

مراجعة الدرس: سكربتات فحص حالة النظام

أنشأت في هذا الدرس مساراً متكاملاً وجاهزاً للإنتاج لفحص حالة النظام وإطلاق التنبيهات. إليك المبادئ الأساسية التي ينبغي الاحتفاظ بها:

  • مصدر الحقيقة: اقرأ المقاييس من /proc/loadavg و/proc/meminfo — فهي مستقرة ومستقلة عن اللغة ومتاحة على كل مضيف Linux
  • حساب الأعداد العشرية: استخدم bc لمقارنة الحدود ذات الفاصلة العائمة؛ إذ إن مقارنة الأعداد الصحيحة في Bash باستخدام -gt تعمل مع الأعداد الصحيحة فقط
  • التكرار على الأقراص: استخدم df --output=pcent,target لفحص كل نظام ملفات مركّب، وليس / فقط
  • التسجيل المنظم: ابدأ كل سطر بطابع زمني بتوقيت UTC ومستوى خطورة، لتسهيل البحث في السجلات باستخدام grep وإرسالها بسلاسة إلى أنظمة التسجيل المركزية
  • أقفال فترة التهدئة: تمنع ملفات القفل التي يتم فحصها باستخدام find -mmin عواصف التنبيهات دون تغيير جدول cron
  • قابلية الدمج: اخرج بالرمز 1 عند إطلاق أي تنبيه، حتى يتكامل السكربت مع Nagios أو Icinga أو أطر المراقبة الأخرى
  • الاختبار: استخدم bash -n لفحص الصياغة، وbash -x لتصحيح الأخطاء عبر التتبع، وعلامة MOCK_MAIL للتحقق من مسار التنبيه على المضيفين السليمين

جدوِل السكربت المكتمل عبر /etc/cron.d/، وستراقب بنيتك التحتية نفسها باستمرار، ولن تطلق تنبيهات إلا عند تجاوز الحدود بشكل مؤثر.

الأسئلة الشائعة

هل درس «إنشاء سكربتات فحص صحة النظام والتنبيه» مجاني؟

نعم — نص درس «إنشاء سكربتات فحص صحة النظام والتنبيه» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Linux Command Line & Bash Scripting Mastery، انتقل إلى CoddyKit PRO. تتضمن دورة Linux Command Line & Bash Scripting Mastery 4 دروس في المجموع.

ماذا ستتعلم في «إنشاء سكربتات فحص صحة النظام والتنبيه»؟

اجمع مقاييس الحمل والذاكرة والقرص وأطلق تنبيهات قائمة على الحدود من خلال سكربتات مجدولة تتمرن على Linux Command Line & Bash Scripting Mastery مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Linux Command Line & Bash Scripting Mastery؟

لا تُشترط خبرة سابقة. Linux Command Line & Bash Scripting Mastery على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «إنشاء سكربتات فحص صحة النظام والتنبيه»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Linux Command Line & Bash Scripting Mastery هذا؟

نعم. كل درس في Linux Command Line & Bash Scripting Mastery يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. أتمتة إنشاء المستخدمين والمجموعات
  2. التحكّم في خدمات systemd وكتابة ملفات الوحدات
  3. أتمتة الأقراص وأنظمة الملفات والضمّ
  4. إنشاء سكربتات فحص صحة النظام والتنبيه
← العودة إلى Linux Command Line & Bash Scripting Mastery