Linux: أتمتة المهام — cron / systemd / journalctl
كل شيء على الخادم يجب أن يكون مؤتمتًا — نسخ احتياطية مجدولة، وتنظيف سجلات، وفحوصات صحة. لينكس يوفر حلول أتمتة تتراوح من البسيط (cron) إلى الحديث (مؤقتات systemd).
📋 المتطلبات المسبقة: يجب أن تعرف بالفعل
- الدرس 21: سكريبت Bash المتقدم
1. ما ستتعلمه
- صياغة مهام cron المجدولة
- كتابة وحدات خدمة systemd
- مؤقت systemd كبديل لـcron
- استعلامات سجلات journalctl
- دوران السجلات بlogrotate
2. قصة "لن أستيقظ الساعة 2 صباحًا لتشغيل سكريبت بعد الآن"
(1) نقطة الألم: نسخ احتياطي يدوي يومي
سكريبت النسخ الاحتياطي لشياو مينغ كان يحتاج تشغيلًا يدويًا كل يوم. ضبط منبهًا — يستيقظ الساعة 2 صباحًا لتشغيل ./backup.sh. بعد أسبوع، كان مرهقًا.
(2) cron حرّره
علّمه بوب crontab:
crontab -e
# أضف:
0 2 * * * /home/alice/scripts/backup.sh > /dev/null 2>&1
منذ ذلك الحين، النظام يشغل النسخ الاحتياطي تلقائيًا يوميًا الساعة 2 صباحًا. شياو مينغ يحتاج فقط فحص السجلات عرضيًا.
(3) الفائدة: دع الآلات تفعل ما يجب أن تفعله الآلات
بعد تعلّم cron، أتمت شياو مينغ كل شيء دفعة واحدة: نسخ احتياطية يومية، وتقارير أسبوعية، وتنظيف سجلات، وفحوصات صحة. وقت عملياته اليومي انخفض من ساعتين إلى 10 دقائق.
3. نقاط المعرفة
(1) crontab — المهام المجدولة
صياغة cron: دقيقة ساعة يوم شهر يوم_أسبوع أمر
دقيقة ساعة يوم شهر يوم_أسبوع أمر
(0-59)(0-23)(1-31)(1-12)(0-7)
(0=الأحد 7=الأحد)
# صياغة خاصة
@reboot # تشغيل عند إعادة التشغيل
@daily # كل يوم الساعة 0:00 (مكافئ لـ0 0 * * *)
@hourly # كل ساعة (مكافئ لـ0 * * * *)
@weekly # كل اثنين الساعة 0:00
@monthly # أول كل شهر الساعة 0:00
أمثلة شائعة:
# عرض 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.
~/.bashrc أو ~/.profile إلخ، وPATH عادةً يشمل فقط /usr/bin:/bin. إذا كان سكريبتيك يعتمد على متغيرات بيئة مخصصة، أضف source لملفات الإعدادات يدويًا في الأعلى، أو استخدم مسارات مطلقة للأوامر في crontab.
(2) خدمة systemd
# مسار وحدة الخدمة
/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
Persistent=true). لسكريبتات دورية بسيطة بدون هذه الحاجات، cron أخف وأبسط. المشاريع الجديدة يجب أن تجرب مؤقت systemd أولًا.
# وحدة المؤقت (بديل 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:
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 — عارض السجلات
# أساسي
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 — دوران السجلات
/etc/cron.daily/logrotate). تحتاج فقط كتابة الإعدادات في /etc/logrotate.d/. بعد تعديل إعداد، استخدم logrotate -d /etc/logrotate.d/your-config في وضع التصحيح للمعاينة، ثم دعه يسري تلقائيًا.
# مواقع الإعدادات
/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
# تعديل 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
# إنشاء خدمة 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
# خدمة النسخ الاحتياطي
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
الإخراج:
TEXTNEXT 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
# عرض أخطاء 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
الإخراج:
TEXTJul 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
# إعداد دوران سجلات لتطبيق مخصص
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
الإخراج:
TEXTreading 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) ▶ مثال شامل: نظام عمليات آلي
#!/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.
📖 ملخص
- crontab:
دقيقة ساعة يوم شهر يوم_أسبوع أمر، وcrontab -eللتعديل - خدمة systemd:
[Service] ExecStart=، وRestart=on-failure - مؤقت systemd:
OnCalendar=، وPersistent=true - journalctl:
-u serviceحسب الخدمة، و-p errحسب المستوى، و-fتتبع واقعي - logrotate:
daily / rotate 7 / compressدوران سجلات تلقائي
📝 تمارين
- أساسي (⭐): هيّئ crontab لتشغيل
dateكل ساعة وإلحاقها بـ/tmp/cron-test.log، ثم استخدم journalctl لعرض سجلات بدء nginx أو sshd - متوسط (⭐⭐): أنشئ
hello.serviceبسيطًا وابدأه (Type=simple)، ثم أنشئ إعداد logrotate لـ/var/log/test-app/*.logبدوران يومي مع الاحتفاظ بـ7 أيام - متقدم (⭐⭐⭐): اكتب مؤقت systemd ينظف الملفات المنتهية في
/tmpيوميًا الساعة 3:00 صباحًا، مع ملف خدمة مقابل، وهيّئ journalctl لعرض سجلات تنفيذه