Linux: إدارة العمليات — ps / top / kill ومراقبة النظام

في لينكس، يُسمّى البرنامج قيد التشغيل عملية (process). إدارة العمليات — معرفة ما يعمل، وكم يستهلك من موارد، وكيفية إيقافه بأمان — هي مهارة أساسية في إدارة الخوادم.

📋 المتطلبات المسبقة: يجب أن تعرف بالفعل

1. ما ستتعلمه


2. قصة خدمة لا تبدأ

(1) نقطة الألم: المنفذ مستخدم بالفعل

واجه شياو مينغ هذه المشكلة عند تشغيل خدمة Node.js:

BASH
node server.js
# Error: listen EADDRINUSE: address already in use :::3000

المنفذ مشغول. لم يعرف أي عملية تستخدم المنفذ 3000 ولا كيفية إيقافها.

(2) تحديد المنفذ وتحريره

BASH
# ابحث عن العملية التي تستخدم المنفذ 3000
ss -tlnp | grep 3000
# LISTEN 0 128 *:3000 *:* users:(("node",pid=1234,fd=20))

# أنهِ العملية
kill 1234

# أعِد تشغيل الخدمة
node server.js

(3) الفائدة: تعارضات المنافذ محسومة

تعلّم شياو مينغ استخدام ss أو lsof لإيجاد العمليات التي تشغل المنافذ، وkill لإرسال إشارات لإنهائها. الآن يحل تعارضات المنافذ خلال 30 ثانية.


3. نقاط المعرفة

(1) ps — لقطة العمليات

BASH
# الاستخدام الأساسي
ps aux               # معلومات تفصيلية عن كل العمليات
ps aux | grep nginx  # تصفية عمليات محددة
ps -ef               # صيغة قياسية

# معاني الحقول الشائعة
# USER    PID  %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
# alice  1234  0.3  1.2 123456 54321 ?        Ssl  10:23   0:01 node server.js

# مخرجات مخصصة
ps -eo pid,user,%cpu,%mem,comm --sort=-%cpu | head -10
الحقل المعنى
PID معرّف العملية
PPID معرّف العملية الأصل
%CPU نسبة استخدام المعالج
%MEM نسبة استخدام الذاكرة
VSZ حجم الذاكرة الافتراضية (كيلوبايت)
RSS حجم الذاكرة الفعلية (كيلوبايت)
STAT حالة العملية (R=قيد التشغيل، S=نائمة، D=غير قابلة للمقاطعة، Z=زومبي، T=متوقفة)
START وقت البدء
TIME وقت المعالج التراكمي
COMMAND اسم الأمر / سطر الأوامر

(2) top/htop — المراقبة في الوقت الفعلي

TEXT
top                             # تشغيل top
top -o %MEM                     # ترتيب حسب الذاكرة
top -u alice                    # عرض عمليات مستخدم محدد فقط
top -bn1 | head -20             # لقطة واحدة

# مفاتيح التشغيل أثناء عمل top
# P    ترتيب حسب المعالج
# M    ترتيب حسب الذاكرة
# k    إنهاء عملية (يطلب PID)
# u    تصفية حسب المستخدم
# q    خروج من top

# htop نسخة محسّنة من top (واجهة أفضل، دعم الفأرة)
htop

(3) kill — إرسال الإشارات

BASH
kill PID                        # إرسال SIGTERM (15)، طلب إنهاء
kill -2 PID                     # إرسال SIGINT (2)، مكافئ لـCtrl+C
kill -9 PID                     # إرسال SIGKILL (9)، إنهاء إجباري
kill -1 PID                     # إرسال SIGHUP (1)، إعادة تحميل الإعدادات
kill -19 PID                    # إرسال SIGSTOP (19)، إيقاف مؤقت للعملية
kill -18 PID                    # إرسال SIGCONT (18)، استئناف العملية

# إنهاء بالاسم
pkill -f "node server.js"       # مطابقة سطر الأوامر
killall nginx                   # إنهاء كل العمليات التي تحمل نفس الاسم
الإشارة الرقم المعنى
SIGHUP 1 قطع الاتصال (إعادة تحميل الإعدادات)
SIGINT 2 مقاطعة (Ctrl+C)
SIGQUIT 3 خروج (مع تفريغ الذاكرة)
SIGKILL 9 إنهاء إجباري (لا يمكن التقاطه/تجاهله)
SIGTERM 15 طلب إنهاء (الافتراضي)
SIGSTOP 19 إيقاف (لا يمكن التقاطه/تجاهله)
SIGCONT 18 استئناف التنفيذ

المبدأ الأساسي: جرّب kill PID (SIGTERM) أولًا. استخدم kill -9 PID (SIGKILL) فقط إذا لم ينفع ذلك. SIGKILL لا يعطي العملية فرصة للتنظيف، مما قد يسبب فقدان البيانات.

⚠️ تحذير: kill -9 (SIGKILL) ينهي العملية إجباريًا دون فرصة للتنظيف — الملفات المفتوحة قد تتلف، ومعاملات قاعدة البيانات قد تنقطع، والملفات المؤقتة تبقى عالقة. استخدم -9 فقط عندما لا يستجيب kill PID (SIGTERM). لا تستخدمه كاختصار.

(4) التنفيذ في الخلفية

TEXT
# & — ضع في الخلفية
node server.js &                 # يعيد الطرفية فور البدء

> 💡 نصيحة: إلحاق `&` بأمر يشغّله في الخلفية، مما يحرر الطرفية فورًا. لكن `&` وحده يعني أن العملية ستُنهى عند إغلاق جلسة الطرفية. لإبقاء العملية تعمل بعد إغلاق الطرفية، ادمجه مع `nohup`: `nohup command &`.
sleep 30 &                       # تشغيل sleep في الخلفية

# jobs/fg/bg — إدارة العمليات الخلفية
jobs                            # عرض العمليات الخلفية
# [1]+  Running                 node server.js &
# [2]-  Running                 sleep 30 &
fg %1                          # إحضار العملية 1 إلى المقدمة
bg %2                          # استئناف العملية 2 المتوقفة في الخلفية

# Ctrl+Z — تعليق العملية الحالية في المقدمة ونقلها للخلفية
# Ctrl+C — إنهاء العملية في المقدمة

# nohup — استمرار التشغيل بعد إغلاق الطرفية
nohup node server.js &
nohup python app.py > app.log 2>&1 &

> ℹ️ ملاحظة: `nohup` + `&` هو المزيج القياسي للأوامر الخلفية المستمرة — `nohup` يتجاهل إشارة SIGHUP (التي تُرسل عند إغلاق الطرفية)، و`&` يضع الأمر في الخلفية. المخرجات تُكتب افتراضيًا إلى `nohup.out`؛ يُنصح بتحديد ملف سجل يدويًا: `nohup command > app.log 2>&1 &`.

(5) ▶ مثال: عرض العمليات

BASH
# عرض كل العمليات
ps aux | head -10

# عرض عمليات مستخدم محدد
ps -u alice -o pid,%cpu,%mem,comm

# أعلى 10 عمليات حسب استخدام المعالج
ps aux --sort=-%cpu | head -11

# عرض شجرة العمليات
ps auxf | head -20

الإخراج:

TEXT
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1 169344 13224 ?        Ss   10:00   0:02 /sbin/init
root         2  0.0  0.0      0     0 ?        S    10:00   0:00 [kthreadd]
alice     1234  0.3  1.2 123456 54321 ?        Ssl  10:23   0:01 node server.js
alice     2345  0.0  0.0   2345   567 pts/0    S+   10:30   0:00 ps aux
PID   USER     %CPU  %MEM  COMMAND
1234  alice    0.3   1.2   node
5678  bob      0.1   0.5   python3
USER   PID %CPU %MEM  COMMAND
root   1   0.0  0.1   /sbin/init
root   456 0.5  2.1   /usr/bin/containerd
alice  1234 8.2  3.4   node server.js
bob    2345 5.1  4.2   python train.py

(6) ▶ مثال: المراقبة في الوقت الفعلي

TEXT
# تشغيل top
top

# العمليات داخل top
# P → ترتيب حسب المعالج
# M → ترتيب حسب الذاكرة
# k → أدخل PID، اضغط Enter، أدخل رقم الإشارة (15 أو 9)، اضغط Enter
# q → خروج

# الوضع غير التفاعلي
top -bn1 | head -15

الإخراج:

TEXT
top - 10:30:01 up  5:23,  2 users,  load average: 0.15, 0.10, 0.05
Tasks: 120 total,   1 running, 119 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.3 us,  0.8 sy,  0.0 ni, 96.5 id,  0.2 wa,  0.0 hi,  0.2 si
MiB Mem :   3936.0 total,    512.0 free,   2048.0 used,   1376.0 buff/cache

(7) ▶ مثال: إنهاء عملية

BASH
# بدء عملية خلفية
sleep 1000 &

# ابحث عنها
ps aux | grep "sleep 1000"
# alice  5678  0.0  0.0   1234   567 pts/0    S    10:23   0:00 sleep 1000

# إنهاء سليم
kill 5678

# إذا لم ينفع ذلك
kill -9 5678

الإخراج:

TEXT
[1]+  Terminated              sleep 1000
alice  5678  0.0  0.0   1234   567 pts/0    S    10:23   0:00 sleep 1000
[1]+  Killed                  sleep 1000

(8) ▶ مثال: التنفيذ في الخلفية عمليًا

BASH
# بدء مهمة طويلة
nohup python train_model.py > train.log 2>&1 &

# عرض السجل
tail -f train.log

# حتى بعد إغلاق الطرفية، train_model.py يستمر في العمل
# بعد إعادة تسجيل الدخول، ps aux سيُظهر أنه لا يزال يعمل

الإخراج:

TEXT
[1] 5678
[2026-07-07 10:23:01] Training epoch 1/100...
[2026-07-07 10:23:15] Loss: 0.5234
[2026-07-07 10:23:30] Training epoch 2/100...

(9) ▶ مثال: تعديل الأولوية بnice/renice

TEXT
# نطاق nice: -20 (أعلى أولوية) إلى 19 (أدنى أولوية)

# البدء بأولوية أقل
nice -n 10 ./heavy-task

# تعديل أولوية عملية قائمة
renice -n 5 -p 1234

# عرض قيم nice للعمليات
ps -eo pid,nice,comm | head -10

(10) ▶ مثال شامل: إدارة الخدمات

BASH
#!/bin/bash
# manage-server.sh - إدارة تطبيق Node.js

APP_NAME="server.js"
APP_DIR="/home/alice/app"
PID_FILE="/tmp/app.pid"

start() {
    if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
        echo "App is already running (PID: $(cat $PID_FILE))"
        exit 1
    fi
    cd "$APP_DIR"
    nohup node "$APP_NAME" > app.log 2>&1 &
    echo $! > "$PID_FILE"
    echo "App started (PID: $!)"
}

stop() {
    if [ ! -f "$PID_FILE" ]; then
        echo "App is not running"
        exit 1
    fi
    PID=$(cat "$PID_FILE")
    echo "Stopping app (PID: $PID)..."
    kill "$PID" 2>/dev/null
    sleep 2
    if kill -0 "$PID" 2>/dev/null; then
        echo "Force killing..."
        kill -9 "$PID" 2>/dev/null
    fi
    rm -f "$PID_FILE"
    echo "Stopped"
}

status() {
    if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
        echo "Running (PID: $(cat $PID_FILE))"
        ps -p $(cat "$PID_FILE") -o pid,%cpu,%mem,etime,comm
    else
        echo "Not running"
    fi
}

case "${1:-status}" in
    start) start ;;
    stop) stop ;;
    restart) stop; start ;;
    *) status ;;
esac

❓ أسئلة شائعة

س: لماذا kill -9 غير آمن؟ ج: kill -9 (SIGKILL) يُجبر العملية على الإنهاء فورًا دون أي تنظيف — الملفات المفتوحة قد تتلف، ومعاملات قاعدة البيانات قد تنقطع، والملفات المؤقتة تُترك عالقة. استخدمه فقط عندما لا يستجيب kill PID (SIGTERM).

س: ما هي العملية الزومبي؟ ج: عملية انتهت لكن عمليةًها الأصل لم تقرأ حالة خروجها. تُترك مدخلة "زومبي" في جدول العمليات (STAT=Z). الزومبي نفسه لا يستهلك موارد، لكن الكثير منها قد يستنزف جدول العمليات. عادةً تحتاج لإنهاء أو إعادة تشغيل العملية الأصل لتنظيفها.

س: ما الفرق بين nohup وdisown؟ ج: nohup يضبط العملية لتتجاهل SIGHUP عند البدء (تُرسل عند إغلاق الطرفية). disown هو أمر bash مدمج يزيل مهمة بدأت فعلًا من جدول مهام الصدفة. nohup command & هو الأسلوب الأكثر شيوعًا.

س: كيف أقيّد استخدام المعالج لعملية ما؟ ج: استخدم cpulimit: cpulimit -l 50 -p PID يقيّدها بـ50% من المعالج. أو استخدم nice لخفض الأولوية. في حاويات Docker، استخدم --cpus للتحديد.

س: كيف أجد أي عملية تستخدم منفذًا محددًا؟ ج: استخدم ss -tlnp | grep :PORT (موصى به) أو lsof -i :PORT (يتطلب lsof) أو fuser PORT/tcp.


📖 ملخص


📝 تمارين

  1. أساسي (⭐): استخدم ps aux --sort=-%cpu لإيجاد أعلى 3 عمليات حسب استخدام المعالج، ثم شغّل sleep 300 &، واطلع عليه بـjobs، وأنهِه بـkill
  2. متوسط (⭐⭐): استخدم nohup لبدء أمر طويل، أغلق الطرفية، أعِد فتحها، وتأكد أنه لا يزال يعمل. ثم استخدم ss -tlnp لعرض كل المنافذ المستمع إليها وعملياتها المرتبطة
  3. متقدم (⭐⭐⭐): اكتب سكريبت إدارة عمليات يدعم أوامر start/stop/status/restart، ويستخدم ملف PID لتتبع العملية، ويُنفّذ إنهاءً سليمًا (SIGTERM أولًا، انتظر 3 ثوانٍ، ثم SIGKILL)
Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%