DevOpsFacile
AccueilParcours de formationCertificationsModulesCheat SheetÀ Propos
DevOpsFacile

Une plateforme d'apprentissage complète pour maîtriser les pratiques DevOps modernes, du débutant à l'expert.

contact@devopsfacile.fr

Formation

  • Parcours de formation
  • Modules

Informations

  • À Propos
  • Conditions d'utilisation
  • Confidentialité
  • Mentions légales

© 2026 DevOps Facile. Tous droits réservés.

Fait avec pour la communauté DevOps

ModulesScripting Bash et administration système Linux12 - Planification avec cron et services systemd

Détails

  • 40 minutes
  • Avancé

Objectifs

  • Configurer des tâches planifiées avec cron et anacron
  • Créer un service systemd personnalisé avec toutes les directives de sécurité
  • Créer un timer systemd comme alternative moderne à cron
  • Diagnostiquer et déboguer les services et timers systemd
Module Scripting Bash et administration système Linux

Exercice 12 : Planification avec cron et services systemd

🎯 Objectifs

À la fin de cet exercice, vous serez capable de :

  • ✅ Écrire des expressions cron et configurer des tâches avec crontab
  • ✅ Créer un fichier unit .service systemd complet avec options de sécurité
  • ✅ Créer un timer .timer systemd pour remplacer cron
  • ✅ Utiliser journalctl pour diagnostiquer les problèmes de services
  • ✅ Appliquer les bonnes pratiques de sécurité des services (sandboxing)

Durée estimée : 40 minutes

Difficulté : ⭐⭐⭐☆☆ (Avancé)

Prérequis : Exercices 09, 10 complétés - scripts Bash


📖 Contexte

Cron est l'outil historique de planification sous Linux. Il est simple et universel. Systemd timers sont l'alternative moderne : plus puissants, mieux intégrés à journalctl, avec retry automatique et une granularité plus fine.

Pour les services longue durée (serveurs, daemons), systemd est incontournable. Pour les scripts périodiques, les deux approches fonctionnent.


📋 Énoncé

Planifiez des tâches de maintenance avec cron et créez un service systemd sécurisé.


🧭 Déroulement de l'exercice

Tâche 1 : Maîtriser la syntaxe cron

bash
# Rappel : format cron
# ┌─────────── minute (0-59)
# │ ┌───────── heure (0-23)
# │ │ ┌─────── jour du mois (1-31)
# │ │ │ ┌───── mois (1-12 ou jan-dec)
# │ │ │ │ ┌─── jour de la semaine (0-7, 0 et 7 = dimanche)
# │ │ │ │ │
# * * * * * commande

# Voir les tâches cron actuelles
crontab -l 2>/dev/null || echo "Aucune tâche cron"

# Créer des tâches de démonstration
cat > mes-taches-cron.txt << 'EOF'
# Nettoyage des logs toutes les nuits à 2h30
30 2 * * * find /var/log -name "*.log" -mtime +30 -delete >> /var/log/nettoyage.log 2>&1

# Sauvegarde chaque jour à 3h, sauf le dimanche
0 3 * * 1-6 /opt/scripts/backup.sh >> /var/log/backup.log 2>&1

# Rapport hebdomadaire chaque lundi à 8h00
0 8 * * 1 /opt/scripts/rapport-semaine.sh | mail -s "Rapport semaine" admin@entreprise.com

# Vérification des disques toutes les 15 minutes
*/15 * * * * /opt/scripts/surveiller-disques.sh 85 >> /var/log/disques.log 2>&1

# Première tâche chaque 1er du mois à minuit
0 0 1 * * /opt/scripts/facturation-mensuelle.sh

# Toutes les 5 minutes, de 9h à 17h, en semaine
*/5 9-17 * * 1-5 /opt/scripts/healthcheck.sh
EOF

echo "Expressions cron créées dans mes-taches-cron.txt"
cat mes-taches-cron.txt

Tester une expression cron :

bash
# Utiliser l'outil en ligne crontab.guru ou la commande suivante
# pour simuler la prochaine exécution

# Installer ncrontab (si disponible) ou tester manuellement
python3 -c "
import re
exprs = [
  '30 2 * * *',
  '*/15 * * * *',
  '*/5 9-17 * * 1-5',
]
for e in exprs:
  print(f'Expression: {e}')
"

Tâche 2 : Créer un service systemd complet

Créez un script de monitoring que systemd va gérer :

bash
sudo mkdir -p /opt/monitoring

sudo tee /opt/monitoring/monitor.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail

LOG_FILE="/var/log/monitoring/system.log"
mkdir -p "$(dirname "$LOG_FILE")"

while true; do
  TIMESTAMP=$(date '+%Y-%m-%dT%H:%M:%S')
  CPU_IDLE=$(top -bn1 | grep "Cpu(s)" | awk '{print $8}' | tr -d '%id,')
  MEM_TOTAL=$(free -m | awk '/^Mem/ {print $2}')
  MEM_USED=$(free -m | awk '/^Mem/ {print $3}')
  MEM_PCT=$(( MEM_USED * 100 / MEM_TOTAL ))
  DISK_PCT=$(df / | awk 'NR==2 {print $5}' | tr -d '%')

  echo "$TIMESTAMP cpu_idle=${CPU_IDLE}% mem=${MEM_PCT}% disk_root=${DISK_PCT}%" >> "$LOG_FILE"

  # Alerte si mémoire > 90%
  if [[ $MEM_PCT -gt 90 ]]; then
    echo "$TIMESTAMP ALERTE: mémoire critique ${MEM_PCT}%" >> "$LOG_FILE"
  fi

  sleep 60  # Attendre 1 minute
done
EOF

sudo chmod +x /opt/monitoring/monitor.sh

Maintenant le fichier unit systemd :

bash
sudo tee /etc/systemd/system/monitoring.service << 'EOF'
[Unit]
Description=Service de monitoring système
Documentation=https://wiki.entreprise.com/monitoring
# Démarrer après le réseau et les cibles essentielles
After=network.target
# Ne pas démarrer si le service de log n'est pas disponible
Wants=syslog.target

[Service]
Type=simple
ExecStart=/opt/monitoring/monitor.sh

# Utilisateur dédié (ne pas tourner en root)
User=monitoring
Group=monitoring

# Répertoire de travail
WorkingDirectory=/opt/monitoring

# Redémarrer automatiquement si le processus meurt
Restart=on-failure
RestartSec=10s

# Délai max pour le démarrage
TimeoutStartSec=30s

# Variables d'environnement
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
EnvironmentFile=-/etc/monitoring/config.env  # Le - signifie : optionnel

# === SANDBOXING ET SÉCURITÉ ===
# Empêcher l'escalade de privilèges
NoNewPrivileges=true

# Protéger les répertoires système en lecture seule
ProtectSystem=strict

# Permettre l'écriture dans /var/log/monitoring
ReadWritePaths=/var/log/monitoring

# Interdire l'accès au répertoire home
ProtectHome=true

# Namespace réseau privé (ne pas utiliser pour les services réseau)
# PrivateNetwork=true

# Filesystem privé temporaire
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

Activer et démarrer le service :

bash
# Créer l'utilisateur dédié
sudo useradd --system --no-create-home --shell /usr/sbin/nologin monitoring 2>/dev/null || true
sudo mkdir -p /var/log/monitoring
sudo chown monitoring:monitoring /var/log/monitoring

# Recharger systemd et activer
sudo systemctl daemon-reload
sudo systemctl enable monitoring.service
sudo systemctl start monitoring.service

# Vérifier l'état
sudo systemctl status monitoring.service

Vérification :

bash
# Le service doit être "active (running)"
systemctl is-active monitoring.service

# Voir les logs en temps réel
journalctl -u monitoring.service -f --no-pager
# Ctrl+C pour arrêter

# Voir les 10 dernières lignes de logs
journalctl -u monitoring.service -n 10

Tâche 3 : Timer systemd (alternative moderne à cron)

bash
# Script de nettoyage
sudo tee /opt/monitoring/nettoyage.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
echo "$(date) : Nettoyage des anciens logs..."
find /var/log/monitoring -name "*.log" -mtime +7 -delete
echo "$(date) : Nettoyage terminé"
EOF
sudo chmod +x /opt/monitoring/nettoyage.sh

# Service one-shot (s'exécute une fois et s'arrête)
sudo tee /etc/systemd/system/nettoyage-logs.service << 'EOF'
[Unit]
Description=Nettoyage des logs de monitoring
After=monitoring.service

[Service]
Type=oneshot
ExecStart=/opt/monitoring/nettoyage.sh
User=monitoring

[Install]
WantedBy=multi-user.target
EOF

# Timer associé au service
sudo tee /etc/systemd/system/nettoyage-logs.timer << 'EOF'
[Unit]
Description=Timer de nettoyage quotidien des logs
Requires=nettoyage-logs.service

[Timer]
# Exécuter chaque jour à 3h00
OnCalendar=*-*-* 03:00:00

# Exécuter au prochain boot si manqué (comme anacron)
Persistent=true

# Décalage aléatoire de 0 à 10 minutes (étaler la charge sur le cluster)
RandomizedDelaySec=10min

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now nettoyage-logs.timer

# Lister tous les timers actifs
systemctl list-timers --all

Vérification :

bash
# Le timer doit apparaître dans la liste avec la prochaine exécution prévue
systemctl list-timers nettoyage-logs.timer

# Forcer l'exécution immédiate pour tester
sudo systemctl start nettoyage-logs.service
journalctl -u nettoyage-logs.service -n 20

Tâche 4 : Diagnostic avec journalctl

bash
# Logs du service depuis le démarrage
journalctl -u monitoring.service --since today

# Logs des 30 dernières minutes
journalctl -u monitoring.service --since "30 minutes ago"

# Filtrer les erreurs seulement (priorité err et plus)
journalctl -u monitoring.service -p err..emerg

# Format JSON pour le parsing
journalctl -u monitoring.service -o json-pretty | head -50

# Logs du boot courant
journalctl -u monitoring.service -b 0

# Logs du boot précédent (utile après un crash)
journalctl -u monitoring.service -b -1

# Nettoyer les vieux journaux (garder seulement les 7 derniers jours)
sudo journalctl --vacuum-time=7d

✅ Vérification du résultat

  • mes-taches-cron.txt contient 5 expressions cron valides
  • systemctl is-active monitoring.service retourne active
  • journalctl -u monitoring.service -n 5 affiche des logs du monitoring
  • systemctl list-timers affiche nettoyage-logs.timer avec une prochaine exécution planifiée
  • Le service tourne avec l'utilisateur monitoring (pas root)

💡 À retenir

OutilUsageAvantage
crontabTâches périodiquesSimple, universel
Systemd timerTâches périodiquesjournalctl, retry, Persistent
Systemd serviceServices continusRestart auto, sandboxing

Sandboxing systemd minimal :

ini
[Service]
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/chemin/dont/je/besoin

✨ Solution Complète

bash
# Créer un service + timer minimal
sudo tee /etc/systemd/system/mon-script.service << 'EOF'
[Unit]
Description=Mon script ponctuel
[Service]
Type=oneshot
ExecStart=/opt/mon-script.sh
User=www-data
NoNewPrivileges=true
ProtectSystem=strict
EOF

sudo tee /etc/systemd/system/mon-script.timer << 'EOF'
[Unit]
Description=Timer mon-script (quotidien à 2h)
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload && sudo systemctl enable --now mon-script.timer
Retour au module

Sur cette page

  • 🎯 Objectifs
  • 📖 Contexte
  • 📋 Énoncé
  • 🧭 Déroulement de l'exercice
  • Tâche 1 : Maîtriser la syntaxe cron
  • Tâche 2 : Créer un service systemd complet
  • Tâche 3 : Timer systemd (alternative moderne à cron)
  • Tâche 4 : Diagnostic avec journalctl
  • ✅ Vérification du résultat
  • 💡 À retenir
  • ✨ Solution Complète