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

الفصل 8.2 - الخدمات المخصصة

أهداف التعلم​

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

  • إنشاء ملف unit لـ systemd
  • تكوين خدمة مخصصة
  • فهم أقسام ملف unit
  • إدارة التبعيات
  • إنشاء خدمات للسكربتات

هيكل ملف Unit​

الموقع​

# النظام
/etc/systemd/system/

# المستخدم
~/.config/systemd/user/

الأولوية:

  • /etc/systemd/system/ (النظام) > /usr/lib/systemd/system/ (الحزم)

التنسيق الأساسي​

[Unit]
Description=وصف الخدمة
After=network.target

[Service]
Type=simple
ExecStart=/chemin/vers/commande
Restart=always

[Install]
WantedBy=multi-user.target

الأقسام الرئيسية​

[Unit]​

[Unit]
Description=خدمتي المخصصة
Documentation=man:mon-service(1)
After=network.target sshd.service
Before=some-service.service
Requires=network.target
Wants=sshd.service
Conflicts=old-service.service

التوجيهات:

  • Description: وصف الخدمة
  • After: يبدأ بعد هذه الوحدات
  • Before: يبدأ قبل هذه الوحدات
  • Requires: تبعية قوية (يفشل إذا فشلت التبعية)
  • Wants: تبعية ضعيفة (يستمر إذا فشلت التبعية)
  • Conflicts: لا يمكن أن يعمل في نفس الوقت

[Service]​

[Service]
Type=simple
ExecStart=/usr/local/bin/mon-script.sh
ExecStartPre=/bin/echo "بدء"
ExecStartPost=/bin/echo "بدأ"
ExecStop=/bin/echo "إيقاف"
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=10
User=monuser
Group=mongroup
WorkingDirectory=/var/lib/monservice
Environment="VAR1=valeur1"
EnvironmentFile=/etc/monservice/env
StandardOutput=journal
StandardError=journal

الأنواع:

  • simple: الأمر الرئيسي (الافتراضي)
  • forking: يتفرع في الخلفية
  • oneshot: تنفيذ لمرة واحدة
  • notify: يُخطر systemd عندما يكون جاهزًا

إعادة التشغيل:

  • no: لا يعيد التشغيل
  • always: يعيد التشغيل دائمًا
  • on-failure: يعيد التشغيل إذا فشل
  • on-success: يعيد التشغيل إذا نجح

[Install]​

[Install]
WantedBy=multi-user.target
Alias=monservice.service

الأهداف الشائعة:

  • multi-user.target: وضع متعدد المستخدمين
  • graphical.target: وضع رسومي
  • default.target: الهدف الافتراضي

أمثلة عملية​

خدمة بسيطة​

# /etc/systemd/system/mon-service.service
[Unit]
Description=خدمتي البسيطة
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mon-script.sh
Restart=always
RestartSec=10
User=www-data
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

التفعيل:

sudo systemctl daemon-reload
sudo systemctl enable mon-service
sudo systemctl start mon-service

خدمة مع سكربت​

#!/bin/bash
# /usr/local/bin/mon-script.sh
# سكربت الخدمة

# وظيفة التنظيف
cleanup() {
echo "إيقاف الخدمة"
# تنظيف...
exit 0
}

# Trap signals
trap cleanup SIGTERM SIGINT

# الحلقة الرئيسية
while true; do
# العمل...
echo "الخدمة نشطة: $(date)"
sleep 60
done

ملف الوحدة:

[Unit]
Description=خدمة مع سكربت
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mon-script.sh
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

خدمة Forking​

[Unit]
Description=خدمة Forking
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/daemon --daemonize
PIDFile=/var/run/daemon.pid
Restart=always

[Install]
WantedBy=multi-user.target

خدمة Oneshot​

[Unit]
Description=سكربت Oneshot
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/init-script.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

متغيرات البيئة​

في ملف الوحدة​

[Service]
Environment="VAR1=valeur1"
Environment="VAR2=valeur2"
EnvironmentFile=/etc/monservice/env

ملف البيئة​

# /etc/monservice/env
VAR1=valeur1
VAR2=valeur2
VAR3="valeur مع مسافات"

إدارة السجلات​

سجل systemd​

# عرض سجلات الخدمة
sudo journalctl -u mon-service

# متابعة السجلات
sudo journalctl -u mon-service -f

# السجلات الحديثة
sudo journalctl -u mon-service -n 50

# منذ تاريخ
sudo journalctl -u mon-service --since "2024-01-01"

إعادة التوجيه​

[Service]
# إلى السجل (الافتراضي)
StandardOutput=journal
StandardError=journal

# إلى ملف
StandardOutput=file:/var/log/monservice.log
StandardError=file:/var/log/monservice-error.log

# تجاهل
StandardOutput=null
StandardError=null

الممارسات الجيدة​

الهيكل​

[Unit]
# وصف واضح
# تبعيات مناسبة

[Service]
# النوع الصحيح
# User/Group غير root إذا أمكن
# إعادة تشغيل مناسبة
# تكوين السجلات

[Install]
# الهدف المناسب

الأمان​

[Service]
# عدم استخدام root إذا أمكن
User=serviceuser
Group=servicegroup

# تقييد القدرات
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

# Chroot إذا أمكن
RootDirectory=/var/lib/monservice

الملخص​

في هذا الفصل، تعلمت:

ملفات الوحدة: هيكل [Unit], [Service], [Install]
الأنواع: simple, forking, oneshot, notify
التبعيات: After, Before, Requires, Wants
إعادة التشغيل: always, on-failure, never
البيئة: Environment, EnvironmentFile
السجلات: journalctl, إعادة توجيه الملفات
الممارسة: إنشاء خدمات للسكربتات والتطبيقات


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

الفصل 8.3: Cron المتقدم وsystemd Timers
الوحدة 9: أمان النظام


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