انتقل إلى المحتوى الرئيسي

مختبر 8.5 - تمرين إضافي: إنشاء 3 خدمات جديدة لـ Wiki.js واختبار طرق مختلفة لإيقافها

الأهداف​

في نهاية هذا المختبر، ستكون قادرًا على:

  • إتقان إنشاء مثيلات إضافية باستخدام قالب systemd (wikijs@.service)
  • مقارنة عدة أوامر "لإيقاف التشغيل" وتحديد تلك التي تعمل بشكل صحيح (ولماذا)
  • استخدام قوالب systemd لإدارة مثيلات متعددة لتطبيق واحد
  • تحديد وإيقاف عمليات Node.js بطرق مختلفة
  • فهم الفروقات بين stop، disable، kill، وطرق الإيقاف الأخرى

المتطلبات المسبقة​

  • تثبيت Ubuntu 24.04
  • الوصول إلى sudo/root
  • تثبيت Wiki.js بالفعل (على الأقل مثيل واحد)
  • معرفة أساسية بـ systemd و MariaDB
  • فتح الطرفية

نظرة عامة​

في هذا المختبر، ستقوم بإنشاء 3 مثيلات جديدة لـ Wiki.js (stage، qa، demo) باستخدام قالب systemd. بعد ذلك، ستختبر طرقًا مختلفة لإيقاف هذه الخدمات وستفهم لماذا تعمل بعض الطرق بينما لا تعمل الأخرى.

هيكلية المثيلات:

البيئةحساب Linuxالمجلدالمنفذقاعدة بيانات MariaDB
stagewikijs_stage/var/www/stage.site13003wikidb_stage
qawikijs_qa/var/www/qa.site13004wikidb_qa
demowikijs_demo/var/www/demo.site13005wikidb_demo

الجزء 1: إعداد قالب systemd​

الخطوة 1: إنشاء قالب systemd​

إذا لم يكن لديك قالب بالفعل، قم بإنشائه:

sudo nano /etc/systemd/system/wikijs@.service

محتوى القالب:

[Unit]
Description=Wiki.js Instance %i
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/node server
Restart=always
User=wikijs_%i
Environment=NODE_ENV=production
WorkingDirectory=/var/www/%i.site1

[Install]
WantedBy=multi-user.target

التفسير:

  • %i يتم استبداله بالمثيل (stage، qa، demo)
  • wikijs_%i يصبح wikijs_stage، wikijs_qa، wikijs_demo
  • /var/www/%i.site1 يصبح /var/www/stage.site1، إلخ.

الخطوة 2: إعادة تحميل systemd​

sudo systemctl daemon-reload

الجزء 2: إنشاء المثيلات الثلاث الجديدة​

الخطوة 1: إنشاء المستخدمين النظاميين​

# إنشاء المستخدمين لكل مثيل
sudo adduser --system --group wikijs_stage
sudo adduser --system --group wikijs_qa
sudo adduser --system --group wikijs_demo

# السماح بالاتصال باستخدام bash
sudo usermod -s /bin/bash wikijs_stage
sudo usermod -s /bin/bash wikijs_qa
sudo usermod -s /bin/bash wikijs_demo

الخطوة 2: إنشاء المجلدات​

# إنشاء المجلدات لكل مثيل
sudo mkdir -p /var/www/stage.site1
sudo mkdir -p /var/www/qa.site1
sudo mkdir -p /var/www/demo.site1

# تحديد المالكين
sudo chown -R wikijs_stage:wikijs_stage /var/www/stage.site1
sudo chown -R wikijs_qa:wikijs_qa /var/www/qa.site1
sudo chown -R wikijs_demo:wikijs_demo /var/www/demo.site1

الخطوة 3: إنشاء قواعد بيانات MariaDB​

# الاتصال بـ MariaDB
sudo mysql -u root -p

في shell MariaDB:

-- إنشاء قواعد البيانات
CREATE DATABASE wikidb_stage;
CREATE DATABASE wikidb_qa;
CREATE DATABASE wikidb_demo;

-- إنشاء المستخدمين
CREATE USER 'wikidb_stage_user'@'localhost' IDENTIFIED BY 'password_stage';
CREATE USER 'wikidb_qa_user'@'localhost' IDENTIFIED BY 'password_qa';
CREATE USER 'wikidb_demo_user'@'localhost' IDENTIFIED BY 'password_demo';

-- منح الامتيازات
GRANT ALL PRIVILEGES ON wikidb_stage.* TO 'wikidb_stage_user'@'localhost';
GRANT ALL PRIVILEGES ON wikidb_qa.* TO 'wikidb_qa_user'@'localhost';
GRANT ALL PRIVILEGES ON wikidb_demo.* TO 'wikidb_demo_user'@'localhost';

FLUSH PRIVILEGES;
EXIT;

الخطوة 4: تنزيل وتثبيت Wiki.js لكل مثيل​

لـ Stage (المنفذ 3003)​

# الاتصال كمستخدم wikijs_stage
sudo su - wikijs_stage

# الانتقال إلى المجلد
cd /var/www/stage.site1

# تنزيل Wiki.js
wget https://github.com/Requarks/wiki/releases/latest/download/wiki-js.tar.gz

# استخراج
tar xzf wiki-js.tar.gz

# حذف الأرشيف
rm wiki-js.tar.gz

# نسخ ملف التكوين
cp config.sample.yml config.yml

# تحرير التكوين
nano config.yml

التكوين لـ stage:

port: 3003
bindIP: 0.0.0.0
db:
type: mariadb
host: localhost
port: 3306
user: wikidb_stage_user
pass: password_stage
db: wikidb_stage
ssl: false

احفظ واخرج. ثم:

exit

لـ QA (المنفذ 3004)​

sudo su - wikijs_qa
cd /var/www/qa.site1
wget https://github.com/Requarks/wiki/releases/latest/download/wiki-js.tar.gz
tar xzf wiki-js.tar.gz
rm wiki-js.tar.gz
cp config.sample.yml config.yml
nano config.yml

التكوين لـ qa:

port: 3004
bindIP: 0.0.0.0
db:
type: mariadb
host: localhost
port: 3306
user: wikidb_qa_user
pass: password_qa
db: wikidb_qa
ssl: false

احفظ واخرج. ثم:

exit

لـ Demo (المنفذ 3005)​

sudo su - wikijs_demo
cd /var/www/demo.site1
wget https://github.com/Requarks/wiki/releases/latest/download/wiki-js.tar.gz
tar xzf wiki-js.tar.gz
rm wiki-js.tar.gz
cp config.sample.yml config.yml
nano config.yml

التكوين لـ demo:

port: 3005
bindIP: 0.0.0.0
db:
type: mariadb
host: localhost
port: 3306
user: wikidb_demo_user
pass: password_demo
db: wikidb_demo
ssl: false

احفظ واخرج. ثم:

exit

الخطوة 5: تفعيل وبدء الخدمات​

# تفعيل وبدء المثيلات الثلاث
sudo systemctl enable --now wikijs@stage
sudo systemctl enable --now wikijs@qa
sudo systemctl enable --now wikijs@demo

الخطوة 6: التحقق​

# التحقق من حالة كل مثيل
sudo systemctl status wikijs@stage --no-pager
sudo systemctl status wikijs@qa --no-pager
sudo systemctl status wikijs@demo --no-pager

# التحقق من أن المنافذ قيد الاستماع
sudo ss -tlnp | grep -E '3003|3004|3005'

الجزء 3: تحديد العمليات والمنافذ​

الملحق 1: أوامر لتحديد عمليات Node.js​

1. عرض جميع عمليات Node مع وحدة systemd​

ps -eo pid,user,unit,cmd | grep -w node

2. النسخة المختصرة: PID + سطر الأوامر​

pgrep -a node

3. حلقة: لكل PID لـ Node، عرض المنافذ التي يستمع إليها​

for pid in $(pgrep node); do lsof -Pan -p "$pid" -i; done

4. عرض جميع المقابس المفتوحة لـ Node مباشرة​

ss -tlnp | grep node

5. لـ PID محدد​

# استبدل 1234 بـ PID الحقيقي
systemctl status --pid=1234
cat /proc/1234/cgroup | grep system.slice

الجزء 4: اختبار طرق مختلفة للإيقاف​

طرق الإيقاف للاختبار​

الأمر A – إيقاف صحيح عبر systemd​

# إيقاف نظيف للمثيل stage
sudo systemctl stop wikijs@stage

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

الأمر B – خطأ منطقي: تعطيل لاحقًا، لا يوقف​

# تعطيل الخدمة ولكن لا يوقفها فورًا
sudo systemctl disable wikijs@qa

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

الأمر C – ⚠️ خطير جدًا: قتل جميع العمليات "wikijs"​

# قتل جميع العمليات المسماة "wikijs"
sudo killall wikijs

التحليل: هذا الأمر خطير لأنه يقتل جميع العمليات المطابقة للاسم، دون تمييز. يمكن أن يؤثر على عمليات أخرى غير ذات صلة.

الأمر D – إيقاف غير مباشر عبر منفذ المثيل Demo (3005)​

# قتل العملية التي تستمع على المنفذ 3005
sudo fuser -k 3005/tcp

التحليل: هذا الأمر يحدد ويقتل العملية التي تستخدم المنفذ 3005. يعمل ولكن أقل نظافة من systemctl.

الأمر E – إيقاف قسري لـ QA (المنفذ 3004) عبر lsof + kill -9​

# العثور على PID الذي يستمع على 3004 وقتله
sudo lsof -ti:3004 | xargs sudo kill -9

التحليل: هذا الأمر يعثر على PID للعملية التي تستمع على المنفذ 3004 ويقتلها بالقوة. يعمل ولكنه يستخدم SIGKILL (القوة الغاشمة).

الأمر F – إعادة تحميل ≠ إيقاف: لا يقطع الخدمة​

# إعادة تحميل التكوين ولكن لا يقطع الخدمة
sudo systemctl reload wikijs@demo

التحليل: هذا الأمر يعيد تحميل تكوين الخدمة ولكنه لا يوقفها. تستمر الخدمة في العمل.

الإجابات الصحيحة فقط​

الأوامر التي توقف الخدمات فعليًا هي:

# الأمر A - إيقاف نظيف
sudo systemctl stop wikijs@stage

# الأمر D - إيقاف عبر المنفذ
sudo fuser -k 3005/tcp

# الأمر E - إيقاف قسري عبر المنفذ
sudo lsof -ti:3004 | xargs sudo kill -9

التحقق من الإيقاف​

# التحقق من عدم وجود خدمة نشطة
sudo systemctl status wikijs@stage
sudo systemctl status wikijs@qa
sudo systemctl status wikijs@demo

# رؤية ما إذا كانت المنافذ لا تزال قيد الاستماع
sudo ss -tlnp | grep node

# التحقق من عمليات Node.js
ps aux | grep node

الجزء 5: التمديد (اختياري)​

إعادة تشغيل جميع المثيلات بشكل نظيف​

# إعادة تشغيل جميع المثيلات في أمر واحد
sudo systemctl restart wikijs@{stage,qa,demo}

مراجعة جميع المنافذ النشطة لـ Node.js حاليًا​

# رؤية جميع المنافذ التي يستمع إليها Node.js
sudo lsof -iTCP -sTCP:LISTEN | grep node

التحقق من أن جميع المنافذ تم تحريرها بعد الإيقاف​

# إيقاف جميع المثيلات
sudo systemctl stop wikijs@{stage,qa,demo}

# التحقق من أن المنافذ خالية
sudo ss -tlnp | egrep '3003|3004|3005'

الملحق 2: أوامر مفيدة لإدارة الخدمات​

1. رؤية جميع المنافذ النشطة والعمليات المرتبطة​

الأمرالتعليق / الهدف
sudo ss -tulnيعرض المنافذ المفتوحة TCP/UDP (الاستماع)، بدون حل DNS (سريع).
sudo lsof -i -P -nيعرض جميع المنافذ والبرامج التي تستخدمها.
sudo lsof -i -P -n | grep nodeيفلتر لرؤية عمليات Node.js فقط.
sudo netstat -tulnpالأمر القديم المكافئ لـ ss، يعرض أيضًا PID.
sudo apt install net-toolsيثبت netstat (ضروري على Ubuntu الحديث).
ps aux | grep nodeيسرد جميع العمليات التي تحتوي على "node".
sudo lsof -i :3000يعرض العملية التي تستمع تحديدًا على المنفذ 3000.
sudo apt install nmapيثبت nmap، ماسح للمنافذ.
sudo nmap -sT -O localhostيفحص المنافذ المفتوحة في TCP على الجهاز المحلي.

2. إدارة خدمات Node.js باستخدام systemd​

الأمرالتعليق / الهدف
systemctl | grep nodeيبحث عن الخدمات التي تحتوي على "node".
systemctl list-units --type=serviceيسرد جميع الخدمات النشطة.
ls /etc/systemd/system/يسرد الملفات .service المثبتة يدويًا.
sudo systemctl stop nom-du-serviceيوقف خدمة بشكل نظيف (مثل: wikijs.service).
sudo systemctl disable nom-du-serviceيمنع الخدمة من البدء في التمهيد التالي.
sudo rm /etc/systemd/system/nom-du-service.serviceيحذف ملف الخدمة.
sudo systemctl daemon-reexecيعيد تحميل systemd بالكامل.
sudo systemctl daemon-reloadيعيد تحميل الملفات .service.
systemctl list-units --type=service | grep -i nodeيسرد خدمات Node.js (غير حساس لحالة الأحرف).
systemctl list-units --type=service | grep 3100يبحث عن الخدمات المرتبطة بالمنفذ 3100.
sudo systemctl reset-failedيعيد تعيين حالة الخدمات الفاشلة.

3. إيقاف عملية يدويًا (إذا لم تكن خدمة)​

الأمرالتعليق / الهدف
sudo kill 1064738يحاول قتل العملية (PID 1064738) بشكل نظيف.
sudo kill -9 1064738قتل العملية بالقوة (SIGKILL).
ps -fp 1072723يعرض تفاصيل العملية 1072723 (صيغة موسعة).
sudo ls -l /proc/1072723/exeيعرض الملف التنفيذي الحقيقي الذي يتم تشغيله بواسطة العملية.
sudo cat /proc/1072723/cmdline | tr '\0' ' 'يعرض الأمر الدقيق الذي أطلق العملية.

4. اكتشاف وإيقاف العمليات المدارة بواسطة PM2​

الأمرالتعليق / الهدف
which pm2يتحقق مما إذا كان pm2 مثبتًا.
pm2 listيسرد التطبيقات المدارة بواسطة PM2.
pm2 stop allيوقف جميع تطبيقات PM2.
pm2 delete allيحذف جميع المراجع للتطبيقات.
pm2 unstartupيعطل بدء التشغيل التلقائي لـ PM2 عند التمهيد.

5. إزالة كاملة لخدمة systemd​

الأمرالتعليق / الهدف
ls /etc/systemd/system/ | grep -i wikiيفلتر الملفات .service المرتبطة بـ "wiki".
sudo systemctl stop wikijs.serviceيوقف الخدمة قبل الإزالة.
sudo systemctl disable wikijs.serviceيعطل الخدمة.
sudo rm /etc/systemd/system/wikijs.serviceيحذف ملف الخدمة.
sudo systemctl daemon-reloadيعيد تحميل تكوين systemd.
sudo systemctl reset-failedيعيد تعيين أخطاء systemd.
systemctl list-units --type=service | grep wikiيتحقق مما إذا كانت الخدمة قد اختفت.
systemctl status wikijs.serviceيتحقق مما إذا كانت الخدمة لا تزال موجودة.
ls -l /etc/systemd/system/يسرد كامل للتحقق يدويًا.
grep -r ExecStart /etc/systemd/system/يبحث عن أسطر التشغيل في جميع الخدمات.

الملحق 3: قائمة شاملة بالأوامر​

أوامر لرؤية المنافذ​

sudo ss -tuln
sudo lsof -i -P -n
sudo lsof -i -P -n | grep node
sudo netstat -tulnp
sudo apt install net-tools
ps aux | grep node
sudo lsof -i :3000
sudo apt install nmap
sudo nmap -sT -O localhost

أوامر systemd​

systemctl | grep node
systemctl list-units --type=service
ls /etc/systemd/system/
sudo systemctl stop nom-du-service
sudo systemctl stop wikijs.service
sudo systemctl disable nom-du-service
sudo rm /etc/systemd/system/nom-du-service.service
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
systemctl | grep 3100
systemctl | grep node
sudo systemctl stop wikijs.service

أوامر kill​

sudo kill 1064738
sudo kill -9 1064738
sudo ss -tuln | grep 3100
sudo lsof -i :3100

أوامر PM2​

which pm2 && pm2 list
pm2 stop all
pm2 delete all
pm2 unstartup

أوامر التشخيص​

sudo systemctl list-units --type=service | grep -i node
ps aux | grep node
ps -fp 1072723
sudo ls -l /proc/1072723/exe
sudo cat /proc/1072723/cmdline | tr '\0' ' '
ls /etc/systemd/system/ | grep -i wiki
ls /lib/systemd/system/ | grep -i wiki
grep -r 3100 /etc/systemd/system/

أوامر الإزالة​

sudo systemctl stop nom.service
sudo systemctl disable nom.service
sudo systemctl daemon-reload
sudo systemctl reset-failed
ls /etc/systemd/system/
ls /etc/systemd/system/ | grep -i wiki
sudo systemctl stop wikijs.service
sudo systemctl disable wikijs.service
sudo rm /etc/systemd/system/wikijs.service
sudo systemctl daemon-reload
sudo systemctl reset-failed
systemctl list-units --type=service | grep wiki
systemctl status wikijs.service
ls -l /etc/systemd/system/
grep -r ExecStart /etc/systemd/system/

تمارين عملية​

تمرين 1: إنشاء وتشغيل المثيلات الثلاث​

  1. قم بإنشاء المثيلات الثلاث (stage، qa، demo) باتباع الخطوات أعلاه
  2. تحقق من أن جميع المثيلات نشطة
  3. تحقق من أن المنافذ 3003، 3004، 3005 قيد الاستماع

تمرين 2: اختبار طرق الإيقاف​

لكل طريقة إيقاف (A، B، C، D، E، F):

  1. أعد تشغيل المثيل المعني أولاً
  2. نفذ أمر الإيقاف
  3. تحقق مما إذا كانت الخدمة قد توقفت بالفعل
  4. وثق النتيجة في جدول

تمرين 3: مقارنة الطرق​

أنشئ جدول مقارنة:

الطريقةالأمريعمل؟لماذا؟موصى به؟
Asystemctl stop؟؟؟
Bsystemctl disable؟؟؟
Ckillall wikijs؟؟؟
Dfuser -k port/tcp؟؟؟
Elsof -ti:port | xargs kill -9؟؟؟
Fsystemctl reload؟؟؟

أسئلة للتفكير​

  1. لماذا systemctl disable لا يوقف خدمة قيد التشغيل بالفعل؟

    • اشرح الفرق بين stop و disable
  2. ما هي المخاطر من استخدام killall لإيقاف الخدمات؟

    • قدم مثالًا لسيناريو يمكن أن يسبب مشاكل
  3. لماذا systemctl reload لا يقطع الخدمة؟

    • اشرح الفرق بين reload و restart
  4. ما الفرق بين kill و kill -9؟

    • في أي حالات ستستخدم كل من هذه الأوامر؟
  5. لماذا تستخدم قالب systemd (wikijs@.service) بدلاً من إنشاء 3 ملفات خدمة منفصلة؟

    • ما هي المزايا والعيوب لكل نهج؟

ملخص طرق الإيقاف​

الطرق الموصى بها ✅​

  1. systemctl stop wikijs@instance - إيقاف نظيف عبر systemd
  2. fuser -k port/tcp - إيقاف عبر المنفذ (يعمل ولكن أقل نظافة)
  3. lsof -ti:port \| xargs kill -9 - إيقاف قسري (الملاذ الأخير)

الطرق التي يجب تجنبها ❌​

  1. systemctl disable - لا يوقف، يعطل فقط عند التمهيد
  2. systemctl reload - يعيد تحميل التكوين ولكن لا يقطع
  3. killall wikijs - خطير جدًا، يمكن أن يؤثر على عمليات أخرى

التحقق النهائي​

تحقق من أنك قد نجحت في:

  • إنشاء قالب systemd wikijs@.service
  • إنشاء المستخدمين النظاميين الثلاثة (wikijs_stage، wikijs_qa، wikijs_demo)
  • إنشاء المجلدات الثلاثة وتثبيت Wiki.js في كل منها
  • إنشاء قواعد البيانات الثلاثة لـ MariaDB
  • تكوين ملفات config.yml بالمنافذ الصحيحة
  • تفعيل وتشغيل المثيلات الثلاث
  • التحقق من أن المنافذ 3003، 3004، 3005 قيد الاستماع
  • اختبار جميع طرق الإيقاف
  • فهم لماذا تعمل بعض الطرق بينما لا تعمل الأخرى
  • الإجابة على أسئلة التفكير

الخطوات التالية​

  • مختبر 8.1: إدارة خدمات systemd (مراجعة)
  • مختبر 8.2: خدمات مخصصة (تعمق)
  • TP 2: Reverse Proxy NGINX (لكشف المثيلات عبر reverse proxy)

تم إنشاء المختبر في: ديسمبر 2024