المختبر 8.6 - إيقاف خدمة
الأهداف
في نهاية هذا المختبر، ستكون قادرًا على:
- تحديد عملية تستخدم منفذًا محددًا
- العثور على خدمة systemd المرتبطة بعملية
- فهم لماذا لا يكفي استخدام
killوحده لإيقاف خدمة - استخدام
systemctl stopوdisableلإيقاف خدمة بشكل دائم - أتمتة تحديد خدمة عبر سكربت bash
- استخدام طرق متقدمة لتشخيص الخدمات
المتطلبات
- وجود موقع Wiki.js قيد التشغيل
- تثبيت nginx
- تثبيت Ubuntu 24.04
- وصول sudo/root
- فتح الطرفية
تثبيت Nginx (إذا لزم الأمر)
sudo apt update
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx
السياق
السيد إريك، مسؤول النظام، يحاول تثبيت وتشغيل تطبيق يسمى Wiki.js على خادم Ubuntu. من المفترض أن يستمع التطبيق على المنفذ 3000، لكنه لا يعمل. بعد عدة محاولات فاشلة، يبدأ إريك سلسلة من التحقيقات لتحديد المشكلة وحلها.
الخطوة 1 – التحقق من المنفذ المستخدم
يبدأ إريك بالتحقق مما إذا كان المنفذ 3000 مستخدمًا بالفعل من قبل خدمة أخرى. يستخدم الأمر التالي:
lsof -i :3000
النتيجة المحصل عليها:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 9744 wikijs 22u IPv4 59242 0t0 TCP *:3000 (LISTEN)
عملية node تستمع على المنفذ 3000. يسجل PID: 9744.
التحليل
- COMMAND :
node- العملية هي تطبيق Node.js - PID :
9744- معرف العملية - USER :
wikijs- المستخدم الذي يشغل العملية - PORT :
3000- المنفذ المستمع
الخطوة 2 – محاولة تحرير المنفذ باستخدام kill
يحاول إريك إيقاف العملية يدويًا:
# محاولة إيقاف نظيف (SIGTERM)
kill -15 9744
# إذا لم ينجح ذلك، إيقاف إجباري (SIGKILL)
kill -9 9744
التحقق
بعد تنفيذ هذه الأوامر، يتحقق إريك مرة أخرى:
lsof -i :3000
النتيجة:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 9842 wikijs 22u IPv4 59243 0t0 TCP *:3000 (LISTEN)
الاستنتاج: يتم إعادة تشغيل العملية تلقائيًا. يظهر PID جديد (9842). كيان آخر (ربما خدمة systemd) يعيد تشغيله.
لماذا تعيد العملية التشغيل؟
تعيد العملية التشغيل تلقائيًا لأنها تُدار بواسطة خدمة systemd مع خيار Restart=always في تكوينها. حتى إذا قتلت العملية، فإن systemd يعيد تشغيلها فورًا.
الخطوة 3 – البحث عن خدمة systemd
يشتبه إريك في وجود خدمة systemd. لذلك يبحث عن اسمها الدقيق.
الأوامر المستخدمة
# سرد جميع الخدمات
systemctl list-units --type=service
# سرد الخدمات المتوقفة
systemctl list-units --type=service --state=exited
# سرد الخدمات الجارية
systemctl list-units --type=service --state=running
# التصفية للعثور على خدمات Wiki
systemctl list-units --type=service --state=running | grep -i wiki
البحث في ملفات الخدمة
# سرد ملفات الخدمة حسب تاريخ التعديل
ls -l --sort=time /etc/systemd/system/
# التصفية للعثور على خدمات Wiki
ls -l /etc/systemd/system/ | grep wiki
عمليات البحث المتقاطعة
# البحث في الاتصالات الشبكية
sudo ss | grep -i wiki
sudo ss | grep -i 3000
# البحث عن عمليات Node.js
ps aux | grep node
# البحث عن الخدمات التي تحتوي على "node"
systemctl | grep node
الأوامر الفائزة
الأوامر الأكثر فعالية لتحديد الخدمة هي:
# العثور على خدمات Wiki الجارية
systemctl list-units --type=service --state=running | grep -i wiki
# البحث عن ملفات خدمة Wiki
ls -l /etc/systemd/system/ | grep wiki
# رؤية عمليات Node.js
ps aux | grep node
# البحث عن الخدمات التي تحتوي على "node"
systemctl | grep node
الفرضية المؤكدة: يبدو أن خدمة تسمى wikijs.service مسؤولة عن العملية.
الخطوة 4 – التحقق من الارتباط بين العملية والمنفذ والخدمة
يقوم إريك بربط العملية node والمنفذ 3000 والخدمة المعنية يدويًا:
تحديد العملية على المنفذ
# رؤية العملية التي تستمع على المنفذ 3000
lsof -i :3000
# رؤية جميع عمليات Node.js ومنافذها
sudo lsof -i -P -n | grep node
# رؤية جميع عمليات Wiki.js
sudo lsof -i -P -n | grep wiki
تحديد ملف الخدمة
# البحث عن ملف الخدمة
ls -l /etc/systemd/system/ | grep wiki
الملف المحدد: wikijs.service
التحقق من الخدمة
# رؤية حالة الخدمة
sudo systemctl status wikijs.service
# رؤية سجلات الخدمة
sudo journalctl -u wikijs.service --no-pager --lines=50
الخطوة 5 – الإيقاف النهائي للخدمة وتحرير المنفذ
يقوم إريك بإيقاف الخدمة بشكل نظيف وتعطيل إعادة تشغيلها التلقائي:
إيقاف الخدمة
# إيقاف الخدمة
sudo systemctl stop wikijs.service
تعطيل إعادة التشغيل التلقائي
# تعطيل الخدمة عند بدء التشغيل
sudo systemctl disable wikijs.service
التحقق النهائي
# التحقق من أن المنفذ تم تحريره
lsof -i :3000
# التحقق من حالة الخدمة
sudo systemctl status wikijs.service
النتيجة: تم تحرير المنفذ 3000 الآن. لن تعيد الخدمة التشغيل تلقائيًا.
الخطوة الإضافية – فحص كامل للمنافذ المفتوحة (اختياري)
للتأكد من الحالة العامة للخادم، يستخدم إريك أداة nmap:
# تثبيت nmap
sudo apt install nmap -y
# فحص المنافذ المفتوحة على localhost
sudo nmap -sT -O localhost
# فحص منفذ محدد
sudo nmap -p 3000 localhost
أسئلة للتفكير
-
لماذا كان المنفذ 3000 يبقى محجوزًا رغم استخدام
kill؟- اشرح دور systemd في إدارة الخدمات
- لماذا لا يكفي
killوحده؟
-
ما هي الطريقة التي تسمح بتحديد اسم الخدمة التي تستخدم منفذًا محددًا؟
- اشرح الطريقة خطوة بخطوة
- ما هي الأوامر الأكثر فعالية؟
-
ما هي الأوامر التي يمكن استخدامها للبحث عن جميع الخدمات التي تحتوي على كلمة
wikiفي اسمها أو وصفها؟- اقترح عدة طرق
-
اقترح سكربت bash يسمح بأتمتة هذا التحقيق.
- يجب أن يحدد السكربت تلقائيًا الخدمة المرتبطة بمنفذ
الملحق 1: طرق أكثر تقدمًا
الطريقة الموصوفة (البحث اليدوي من المنفذ باستخدام lsof، ps، systemctl، إلخ) هي موثوقة ولكنها يدوية. هناك طرق أكثر تقدمًا وأتمتة، مفيدة للبيئات المعقدة، مثل الخوادم الإنتاجية أو العناقيد.
1. systemd-cgls أو systemd-cgtop
تتيح هذه الأدوات عرض شجرة الخدمات والعمليات التي يتحكم فيها systemd.
# رؤية الشجرة الكاملة
systemd-cgls
# التصفية لـ Wiki.js
systemd-cgls | grep -i wiki
# التصفية لـ PostgreSQL
systemd-cgls | grep -i postgres
# التصفية لـ Nginx
systemd-cgls | grep -i nginx
# رؤية شجرة خدمة محددة
systemd-cgls /system.slice/wikijs.service
# سرد cgroups
ls /sys/fs/cgroup/system.slice/ | grep wiki
# رؤية عمليات Wiki
ps -ef | grep wiki
2. systemctl status مع --property
يمكنك استجواب جميع الخدمات وطلب رؤية MainPID، ثم التقاطع مع المنفذ:
# رؤية جميع MainPID للخدمات
systemctl show --all --property=MainPID --no-pager
# لخدمة محددة
systemctl show wikijs.service --property=MainPID
ثم:
# رؤية PID الذي يستخدم المنفذ 3000
sudo lsof -i :3000
وتقارن MainPID مع PID الذي يستخدم المنفذ.
3. استخدام fuser لقتل العملية مباشرة عبر المنفذ
# قتل العملية المرتبطة بالمنفذ 3000
sudo fuser -k 3000/tcp
تنبيه: هذه الطريقة لا تعطل الخدمة، لذا يمكن أن تعيد التشغيل. إنها مفيدة في سكربت مؤقت.
4. باستخدام ss --processes
# رؤية العملية التي تستمع على المنفذ 3000
sudo ss -lptn 'sport = :3000'
هذا يظهر مباشرة:
- المنفذ،
- البروتوكول،
- العملية،
- وأحيانًا اسم الخدمة إذا تم تكوينه بشكل جيد.
5. استخدام netstat مع --program (إذا كان متاحًا)
# تثبيت net-tools إذا لزم الأمر
sudo apt update
sudo apt install net-tools
# رؤية العملية على المنفذ 3000
sudo netstat -tulnp | grep 3000
يسمح بتحديد البرنامج الذي يستخدم منفذًا مباشرة. يمكنك التقاطع مع systemctl:
# رؤية تفاصيل العملية
ps -p <PID> -o pid,cmd
6. عبر سجلات systemd
إذا تم تشغيل الخدمة بشكل جيد بواسطة systemd، يمكنك القيام بـ:
# رؤية سجلات الخدمة
journalctl -u wikijs.service
# رؤية السجلات في الوقت الحقيقي
journalctl -u wikijs.service -f
# رؤية السطور الأخيرة
journalctl -u wikijs.service --no-pager --lines=50
هذا يظهر لك تاريخ التنفيذ، بما في ذلك المنفذ المستمع.
الملحق 2: أتمتة تحديد الخدمة
سكربت Bash: تحديد خدمة systemd وراء منفذ
قم بإنشاء ملف recherche_service_port.sh:
#!/bin/bash
# طلب من المستخدم إدخال رقم المنفذ
read -p "أدخل رقم المنفذ (مثال: 3000) : " PORT
# الخطوة 1: الحصول على PID للعملية التي تستمع على هذا المنفذ
PID=$(sudo lsof -i :$PORT -sTCP:LISTEN -t)
# التحقق مما إذا تم العثور على PID
if [ -z "$PID" ]; then
echo "لا يبدو أن هناك عملية تستمع على المنفذ $PORT."
exit 1
fi
echo "تم الكشف عن عملية على المنفذ $PORT : PID = $PID"
# الخطوة 2: عرض المعلومات حول العملية
echo "الأمر المرتبط بهذا PID :"
ps -p $PID -o pid,cmd
# الخطوة 3: البحث عن خدمة systemd التي تنتمي إليها هذا PID
echo ""
echo "البحث عن خدمة systemd المقابلة..."
# الطريقة 1: البحث عبر systemctl
SERVICE=$(systemctl | grep $PID | awk '{print $1}')
# الطريقة 2: إذا لم يتم العثور عليها، البحث في ملفات الخدمة
if [ -z "$SERVICE" ]; then
echo "البحث في ملفات الخدمة..."
# البحث عن PID في cgroups
for service_file in /etc/systemd/system/*.service; do
if [ -f "$service_file" ]; then
service_name=$(basename "$service_file")
# التحقق مما إذا كانت الخدمة نشطة وتطابق PID
main_pid=$(systemctl show "$service_name" --property=MainPID --value 2>/dev/null)
if [ "$main_pid" = "$PID" ]; then
SERVICE="$service_name"
break
fi
fi
done
fi
# الطريقة 3: البحث عبر cgroup
if [ -z "$SERVICE" ]; then
cgroup=$(cat /proc/$PID/cgroup 2>/dev/null | grep system.slice | cut -d: -f3)
if [ -n "$cgroup" ]; then
SERVICE=$(basename "$cgroup" .service)
fi
fi
if [ -z "$SERVICE" ]; then
echo "لم يتم العثور على خدمة systemd تلقائيًا لـ PID $PID."
echo "التحقق اليدوي ممكن باستخدام:"
echo " systemctl status <nom_du_service>"
echo "أو البحث في /etc/systemd/system/"
echo ""
echo "الأوامر المفيدة:"
echo " ps -p $PID -o pid,cmd"
echo " systemctl list-units --type=service | grep -i wiki"
echo " ls -l /etc/systemd/system/ | grep wiki"
else
echo "تم الكشف عن خدمة systemd : $SERVICE"
echo ""
echo "حالة الخدمة:"
systemctl status $SERVICE --no-pager -l
echo ""
echo "لإيقاف الخدمة:"
echo " sudo systemctl stop $SERVICE"
echo " sudo systemctl disable $SERVICE"
fi
الاستخدام
- احفظ السكربت في ملف:
nano recherche_service_port.sh
- اجعله قابلًا للتنفيذ:
chmod +x recherche_service_port.sh
- نفذه:
./recherche_service_port.sh
ما تعلمته
- كيفية ربط منفذ بعملية (
lsof) - كيفية الرجوع إلى الخدمة عبر
systemctlوgrep - كيفية أتمتة تشخيص الشبكة في Bash
- كيفية استخدام cgroups لتحديد الخدمات
ملخص الأوامر المهمة
| الأمر | الوصف |
|---|---|
lsof -i :3000 | رؤية العملية التي تستمع على المنفذ 3000 |
kill -15 PID | إيقاف نظيف للعملية (SIGTERM) |
kill -9 PID | إيقاف إجباري للعملية (SIGKILL) |
systemctl list-units --type=service --state=running | سرد الخدمات النشطة |
systemctl stop wikijs.service | إيقاف خدمة |
systemctl disable wikijs.service | تعطيل خدمة عند بدء التشغيل |
systemctl status wikijs.service | رؤية حالة خدمة |
journalctl -u wikijs.service | رؤية سجلات خدمة |
sudo ss -lptn 'sport = :3000' | رؤية العملية على منفذ باستخدام ss |
sudo fuser -k 3000/tcp | قتل العملية على منفذ |
التحقق النهائي
تحقق من أنك قد نجحت في:
- تحديد العملية التي تستخدم المنفذ 3000
- فهم لماذا لا يكفي
killوحده - العثور على خدمة systemd المسؤولة
- إيقاف وتعطيل الخدمة بشكل صحيح
- التحقق من أن المنفذ تم تحريره
- استخدام الطرق المتقدمة للتشخيص
- إنشاء واستخدام سكربت الأتمتة
- الإجابة على أسئلة التفكير
الخطوات التالية
- المختبر 8.1: إدارة خدمات systemd (مراجعة)
- المختبر 8.5: مثيلات Wiki.js متعددة (إنشاء مثيلات متعددة)
- TP 3: اختبار systemd والعمليات (تقييم)
تم إنشاء المختبر في: ديسمبر 2024