Linux: أتمتة المهام — cron / systemd / journalctl

كل شيء على الخادم يجب أن يكون مؤتمتًا — نسخ احتياطية مجدولة، وتنظيف سجلات، وفحوصات صحة. لينكس يوفر حلول أتمتة تتراوح من البسيط (cron) إلى الحديث (مؤقتات systemd).

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

1. ما ستتعلمه


2. قصة "لن أستيقظ الساعة 2 صباحًا لتشغيل سكريبت بعد الآن"

(1) نقطة الألم: نسخ احتياطي يدوي يومي

سكريبت النسخ الاحتياطي لشياو مينغ كان يحتاج تشغيلًا يدويًا كل يوم. ضبط منبهًا — يستيقظ الساعة 2 صباحًا لتشغيل ./backup.sh. بعد أسبوع، كان مرهقًا.

(2) cron حرّره

علّمه بوب crontab:

BASH
crontab -e
# أضف:
0 2 * * * /home/alice/scripts/backup.sh > /dev/null 2>&1

منذ ذلك الحين، النظام يشغل النسخ الاحتياطي تلقائيًا يوميًا الساعة 2 صباحًا. شياو مينغ يحتاج فقط فحص السجلات عرضيًا.

(3) الفائدة: دع الآلات تفعل ما يجب أن تفعله الآلات

بعد تعلّم cron، أتمت شياو مينغ كل شيء دفعة واحدة: نسخ احتياطية يومية، وتقارير أسبوعية، وتنظيف سجلات، وفحوصات صحة. وقت عملياته اليومي انخفض من ساعتين إلى 10 دقائق.


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

(1) crontab — المهام المجدولة

صياغة cron: دقيقة ساعة يوم شهر يوم_أسبوع أمر

TEXT
 دقيقة  ساعة  يوم  شهر  يوم_أسبوع  أمر
(0-59)(0-23)(1-31)(1-12)(0-7)
                      (0=الأحد 7=الأحد)
TEXT
# صياغة خاصة
@reboot     # تشغيل عند إعادة التشغيل
@daily      # كل يوم الساعة 0:00 (مكافئ لـ0 0 * * *)
@hourly     # كل ساعة (مكافئ لـ0 * * * *)
@weekly     # كل اثنين الساعة 0:00
@monthly    # أول كل شهر الساعة 0:00

أمثلة شائعة:

TEXT
# عرض cron للمستخدم الحالي
crontab -l

# تعديل crontab
crontab -e

# حذف كل مهام cron
crontab -r

# أمثلة شائعة
0 2 * * * /scripts/backup.sh              # يوميًا الساعة 2:00
*/5 * * * * /scripts/health-check.sh      # كل 5 دقائق
0 0 * * 0 /scripts/weekly-report.sh       # كل أحد الساعة 0:00
0 0 1 * * /scripts/monthly-cleanup.sh     # أول كل شهر
0 9-17 * * 1-5 /scripts/business-hours.sh # أيام العمل 9-17، كل ساعة
⚠️ تحذير: crontab -r يحذف كل مهام cron للمستخدم الحالي بدون تأكيد! الحذف العرضي لا يمكن استرجاعه إلا من نسخة احتياطية. استخدم دائمًا crontab -l للنسخ الاحتياطي قبل الحذف، أو طوّر عادة التعديل بـcrontab -e بدلًا من الحذف بـcrontab -r.

💡 نصيحة: بيئة تنفيذ cron تختلف عن الصدفة التفاعلية — لا تحمّل ~/.bashrc أو ~/.profile إلخ، وPATH عادةً يشمل فقط /usr/bin:/bin. إذا كان سكريبتيك يعتمد على متغيرات بيئة مخصصة، أضف source لملفات الإعدادات يدويًا في الأعلى، أو استخدم مسارات مطلقة للأوامر في crontab.

(2) خدمة systemd

BASH
# مسار وحدة الخدمة
/etc/systemd/system/myapp.service

# البنية الأساسية
[Unit]
Description=My Web Application
After=network.target

[Service]
Type=simple
User=alice
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

# الاستخدام
sudo systemctl daemon-reload     # إعادة تحميل الإعدادات
sudo systemctl start myapp       # بدء
sudo systemctl enable myapp      # تفعيل مع بدء النظام
sudo systemctl status myapp      # عرض الحالة
sudo journalctl -u myapp -f      # عرض السجلات

(3) مؤقت systemd

💡 نصيحة: اختر مؤقت systemd أم cron؟ إذا كانت مهمتك المجدولة تعتمد على خدمات أخرى، أو تحتاج تسجيل، أو قد تُفوت أثناء توقف النظام (تحتاج تعويضًا)، اختر مؤقت systemd (اضبط Persistent=true). لسكريبتات دورية بسيطة بدون هذه الحاجات، cron أخف وأبسط. المشاريع الجديدة يجب أن تجرب مؤقت systemd أولًا.

BASH
# وحدة المؤقت (بديل cron)
/etc/systemd/system/backup.timer

[Unit]
Description=Daily Backup Timer

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

# الخدمة المقابلة
/etc/systemd/system/backup.service

[Unit]
Description=Daily Backup Service

[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh

# الاستخدام
sudo systemctl enable --now backup.timer
sudo systemctl list-timers --all

صياغة OnCalendar:

TEXT
OnCalendar=daily                    # كل يوم الساعة 0:00
OnCalendar=hourly                   # كل ساعة
OnCalendar=*-*-* 02:00:00           # كل يوم الساعة 2:00
OnCalendar=Mon *-*-* 03:00:00       # كل اثنين الساعة 3:00
OnCalendar=*-*-1 00:00:00           # أول كل شهر
OnCalendar=*:0/5                    # كل 5 دقائق

(4) journalctl — عارض السجلات

BASH
# أساسي
journalctl                           # كل السجلات
journalctl -u nginx                  # خدمة محددة
journalctl -u nginx -f               # تتبع في الوقت الفعلي
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --until "2026-07-07 10:00"
journalctl -p err                    # مستوى خطأ وأعلى فقط
journalctl -p err -u nginx           # سجلات أخطاء nginx

# الإدارة
journalctl --disk-usage              # فحص استخدام قرص السجلات
sudo journalctl --vacuum-size=500M   # تحديد حجم السجلات
sudo journalctl --vacuum-time=7d     # الاحتفاظ بـ7 أيام

(5) logrotate — دوران السجلات

💡 نصيحة: logrotate يُنفَّذ تلقائيًا يوميًا بواسطة cron النظامي (سكريبت في /etc/cron.daily/logrotate). تحتاج فقط كتابة الإعدادات في /etc/logrotate.d/. بعد تعديل إعداد، استخدم logrotate -d /etc/logrotate.d/your-config في وضع التصحيح للمعاينة، ثم دعه يسري تلقائيًا.

BASH
# مواقع الإعدادات
/etc/logrotate.conf                  # الإعدادات العامة
/etc/logrotate.d/                    # إعدادات لكل تطبيق

# مثال: دوران سجلات Nginx
/var/log/nginx/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 640 www-data adm
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

التوجيهات الشائعة:

التوجيه المعنى
daily/weekly/monthly تردد الدوران
rotate N الاحتفاظ بـN نسخ مؤرشفة
compress ضغط الأرشيفات (gzip)
delaycompress تأخير الضغط دورة واحدة
missingok لا خطأ إذا كان الملف مفقودًا
notifempty لا تدور الملفات الفارغة
size 100M دوران فقط عند بلوغ الملف الحجم المحدد
maxage 30 حذف أرشيفات أقدم من 30 يومًا

(6) ▶ مثال: إعداد crontab

TEXT
# تعديل crontab
crontab -e

# اكتب المحتوى التالي
# ┌───── دقيقة (0-59)
# │ ┌───── ساعة (0-23)
# │ │ ┌───── يوم الشهر (1-31)
# │ │ │ ┌───── شهر (1-12)
# │ │ │ │ ┌───── يوم الأسبوع (0-7، 0=الأحد)
# * * * * * أمر

# نسخ احتياطي آلي يوميًا الساعة 2:00 صباحًا
0 2 * * * /home/alice/scripts/backup.sh

# فحص صحة كل 5 دقائق
*/5 * * * * /home/alice/scripts/health-check.sh

# تقرير أسبوعي كل اثنين الساعة 3:00 صباحًا
0 3 * * 1 /home/alice/scripts/weekly-report.sh

# تنظيف أرشيفات أول كل شهر
0 0 1 * * /home/alice/scripts/cleanup.sh

(7) ▶ مثال: إنشاء خدمة systemd

BASH
# إنشاء خدمة systemd لتطبيق Node.js
sudo tee /etc/systemd/system/webapp.service << 'EOF'
[Unit]
Description=Node.js Web Application
Documentation=https://example.com/docs
After=network.target

[Service]
Type=simple
User=alice
Group=alice
WorkingDirectory=/opt/webapp
Environment=NODE_ENV=production
Environment=PORT=3000
ExecStart=/usr/bin/node /opt/webapp/server.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=10

ProtectSystem=full
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now webapp
sudo systemctl status webapp

الإخراج:

TEXT
● webapp.service - Node.js Web Application
     Loaded: loaded (/etc/systemd/system/webapp.service; enabled)
     Active: active (running) since Tue 2026-07-07 10:23:45 UTC
   Main PID: 5678 (node)
      Tasks: 12 (limit: 4915)
     Memory: 45.2M
        CPU: 1.234s

(8) ▶ مثال: مؤقت systemd بديلًا لـcron

BASH
# خدمة النسخ الاحتياطي
sudo tee /etc/systemd/system/backup.service << 'EOF'
[Unit]
Description=Daily Backup

[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
User=alice
EOF

# مؤقت النسخ الاحتياطي
sudo tee /etc/systemd/system/backup.timer << 'EOF'
[Unit]
Description=Run backup daily at 2am
Requires=backup.service

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
sudo systemctl list-timers --all

الإخراج:

TEXT
NEXT                        LEFT          LAST                        PASSED
Tue 2026-07-07 02:00:00 UTC 15h left      Mon 2026-07-06 02:00:00 UTC 9h ago
n/a                         n/a           n/a                         n/a

1 timers listed.

(9) ▶ مثال: استعلامات سجلات journalctl

BASH
# عرض أخطاء nginx من الساعة الماضية
journalctl -u nginx -p err --since "1 hour ago"

# عرض كل سجلات الأمس
journalctl --since yesterday --until today

# عرض سجلات PID محدد
journalctl _PID=1234

# تتبع خدمات متعددة في الوقت الفعلي
journalctl -u nginx -u webapp -f

# تصدير السجلات إلى ملف
journalctl -u webapp --since "2026-07-06" > webapp-logs.txt

# فحص استخدام قرص السجلات
journalctl --disk-usage
# Archived and active journals take up 512.0M

# تنظيف
sudo journalctl --vacuum-size=200M

الإخراج:

TEXT
Jul 07 10:23:45 server nginx[1234]: GET /api/users 200 1234
Jul 07 10:23:50 server nginx[1234]: POST /api/data 500 0
Jul 07 10:24:01 server webapp[5678]: Error: ECONNREFUSED
-- Logs begin at Mon 2026-07-06 00:00:01 --
Jul 07 09:00:00 server sshd[890]: Accepted publickey for alice
Archived and active journals take up 512.0M
Deleted archived journals: 23
Vacuuming done, freed 312.0M of archived journals

(10) ▶ مثال: إعداد logrotate

BASH
# إعداد دوران سجلات لتطبيق مخصص
sudo tee /etc/logrotate.d/custom-app << 'EOF'
/var/log/custom-app/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 640 www-data www-data
    sharedscripts
    postrotate
        systemctl reload custom-app > /dev/null 2>&1 || true
    endscript
}
EOF

# اختبار الإعدادات
sudo logrotate -d /etc/logrotate.d/custom-app

# تنفيذ إجباري يدوي
sudo logrotate -f /etc/logrotate.d/custom-app

الإخراج:

TEXT
reading config file /etc/logrotate.d/custom-app
Handling 1 logs

rotating pattern: /var/log/custom-app/*.log
rotating 14 kept versions
considering log /var/log/custom-app/app.log
  log needs rotating
renaming /var/log/custom-app/app.log to /var/log/custom-app/app.log.1
creating new /var/log/custom-app/app.log mode=0640 user=www-data group=www-data

(11) ▶ مثال شامل: نظام عمليات آلي

BASH
#!/bin/bash
# setup-automation.sh - إعداد نظام عمليات آلي

set -euo pipefail

echo "=== Setting Up Automated Ops System ==="

# 1. إنشاء دليل السكريبتات
mkdir -p /opt/scripts

# 2. سكريبت النسخ الاحتياطي
cat > /opt/scripts/backup.sh << 'BACKUPEOF'
#!/bin/bash
# Auto backup - triggered daily at 2 AM by cron or systemd timer

SOURCE="/var/www"
DEST="/backup"
RETENTION=30

mkdir -p "$DEST"
BACKUP_FILE="${DEST}/backup_$(date +%Y%m%d).tar.gz"

tar -czf "$BACKUP_FILE" \
    --exclude=node_modules \
    --exclude=.git \
    "$SOURCE" 2>/dev/null

# Clean expired backups
find "$DEST" -name "backup_*.tar.gz" -mtime +$RETENTION -delete

# Log
echo "[$(date)] Backup: $BACKUP_FILE ($(du -h "$BACKUP_FILE" | cut -f1))" >> /var/log/backup.log
BACKUPEOF
chmod +x /opt/scripts/backup.sh

# 3. سكريبت فحص الصحة
cat > /opt/scripts/health-check.sh << 'HEALTHEOF'
#!/bin/bash
# Health check - runs every 5 minutes

WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
SERVICES=("nginx" "postgresql" "webapp")

for svc in "${SERVICES[@]}"; do
    if ! systemctl is-active --quiet "$svc"; then
        MESSAGE="❌ $svc service abnormal $(date)"
        echo "$MESSAGE" | mail -s "Service Alert" admin@example.com
        # curl -X POST -d "text=$MESSAGE" "$WEBHOOK_URL"
    fi
done

# Disk check
DISK_USAGE=$(df -h / | tail -1 | awk '{print $5}' | tr -d '%')
if [ "$DISK_USAGE" -gt 85 ]; then
    echo "⚠️ Disk usage: ${DISK_USAGE}%" >> /var/log/disk-alert.log
fi
HEALTHEOF
chmod +x /opt/scripts/health-check.sh

# 4. إعداد cron
(crontab -l 2>/dev/null; echo "") | crontab -
(crontab -l 2>/dev/null; echo "# Auto backup - daily at 2:00") | crontab -
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/scripts/backup.sh > /dev/null 2>&1") | crontab -
(crontab -l 2>/dev/null; echo "# Health check - every 5 minutes") | crontab -
(crontab -l 2>/dev/null; echo "*/5 * * * * /opt/scripts/health-check.sh > /dev/null 2>&1") | crontab -
(crontab -l 2>/dev/null; echo "# Log cleanup - every Sunday") | crontab -
(crontab -l 2>/dev/null; echo "0 0 * * 0 journalctl --vacuum-size=200M > /dev/null 2>&1") | crontab -

echo ""
echo "=== Automated Ops System Setup Complete ==="
echo "Configured tasks:"
crontab -l | grep -v "^#"
echo ""
echo "Manual verification: crontab -l"

❓ أسئلة شائعة

س: هل متغيرات بيئة crontab نفسها كما في الطرفية؟ ج: لا! PATH في بيئة تنفيذ cron محدود جدًا (عادةً /usr/bin:/bin). إذا كان سكريبتيك يعتمد على PATH المعرف في ~/.bashrc، إما اضبط PATH في أعلى السكريبت أو استخدم مسارات مطلقة في أمر cron.

س: ما مميزات مؤقت systemd مقارنة بـcron؟ ج: 1) إدارة الاعتماديات: المؤقتات يمكن أن تعتمد على خدمات أخرى. 2) تكامل السجلات: تسجيل journalctl تلقائي. 3) التنفيذ الفائت: Persistent=true يعوّض عند الإقلاع التالي. 4) دقة أعلى: يدعم دقة ملي ثانية. 5) إدارة موحدة: systemctl list-timers.

س: هل سجلات journalctl ستملأ القرص الصلب؟ ج: الحد الأقصى الافتراضي هو 10% من القرص (لكن ليس أكثر من 4 غيغابايت). استخدم journalctl --vacuum-size=500M أو اضبط SystemMaxUse=500M في /etc/systemd/journald.conf للتحديد.

س: هل logrotate يعمل تلقائيًا أم أحتاج إعداد cron؟ ج: logrotate يُنفَّذ يوميًا بواسطة مهمة cron المدمجة في النظام (في /etc/cron.daily/logrotate). تحتاج فقط إعداد القواعد في /etc/logrotate.d/ — لا حاجة لإعداد cron إضافي.

س: كيف أصحح مشكلة عدم تنفيذ crontab؟ ج: استكشاف بثلاث خطوات: 1) تحقق أن خدمة cron تعمل: systemctl status cron. 2) تحقق من سجلات cron: grep CRON /var/log/syslog. 3) شغّل السكريبت يدويًا للتأكد أنه يعمل: bash /path/to/script.sh.


📖 ملخص


📝 تمارين

  1. أساسي (⭐): هيّئ crontab لتشغيل date كل ساعة وإلحاقها بـ/tmp/cron-test.log، ثم استخدم journalctl لعرض سجلات بدء nginx أو sshd
  2. متوسط (⭐⭐): أنشئ hello.service بسيطًا وابدأه (Type=simple)، ثم أنشئ إعداد logrotate لـ/var/log/test-app/*.log بدوران يومي مع الاحتفاظ بـ7 أيام
  3. متقدم (⭐⭐⭐): اكتب مؤقت systemd ينظف الملفات المنتهية في /tmp يوميًا الساعة 3:00 صباحًا، مع ملف خدمة مقابل، وهيّئ journalctl لعرض سجلات تنفيذه
Web-Tutorial.com

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

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

100%