Les timers systemd sont le remplacement moderne de cron sur les systèmes Linux. Ils offrent tout ce que cron propose — planification récurrente et ponctuelle — avec en plus une journalisation intégrée, la gestion des dépendances, le contrôle des ressources et la capacité de rattraper les exécutions manquées. Si vous administrez des serveurs Linux, passer de cron aux timers systemd signifie moins de défaillances silencieuses et une bien meilleure visibilité sur ce que font vos tâches planifiées.
Ce guide vous accompagne dans la création de timers de zéro, la conversion de cron jobs existants et l’utilisation de fonctionnalités avancées comme les délais aléatoires et la planification persistante.
Prérequis
- Un système Linux utilisant systemd (Ubuntu 16.04+, CentOS 7+, Debian 8+ ou toute distribution moderne)
- Accès root ou sudo
- Connaissance de base de systemctl et des fichiers d’unité
Fonctionnement des timers systemd
Un timer systemd se compose de deux fichiers d’unité :
- Une unité
.service— définit ce qu’il faut exécuter (la commande ou le script) - Une unité
.timer— définit quand l’exécuter (la planification)
L’unité timer active son unité service correspondante selon la planification. Les deux fichiers doivent partager le même nom de base (par exemple, backup.service et backup.timer), sauf si vous spécifiez explicitement une unité différente avec Unit=.
Cette séparation est un avantage majeur par rapport à cron : l’unité service peut être testée indépendamment, redémarrée en cas d’échec et inspectée avec les outils standard de systemd.
Créer votre premier timer
Créons un timer qui exécute un script de nettoyage chaque jour à 2h00 du matin.
Étape 1 : Créer l’unité service
sudo nano /etc/systemd/system/daily-cleanup.service
[Unit]
Description=Daily temporary file cleanup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cleanup.sh
Le Type=oneshot indique à systemd que ce processus s’exécute jusqu’à la fin puis se termine — ce n’est pas un daemon persistant. C’est le type approprié pour les tâches planifiées.
Créez le script référencé :
sudo tee /usr/local/bin/cleanup.sh > /dev/null << 'EOF'
#!/bin/bash
find /tmp -type f -mtime +7 -delete
find /var/log -name "*.gz" -mtime +30 -delete
echo "Cleanup completed at $(date)"
EOF
sudo chmod +x /usr/local/bin/cleanup.sh
Étape 2 : Créer l’unité timer
sudo nano /etc/systemd/system/daily-cleanup.timer
[Unit]
Description=Run daily cleanup at 2:00 AM
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Directives clés :
| Directive | Fonction |
|---|---|
OnCalendar | Planification basée sur le calendrier (comme cron) |
Persistent=true | Exécuter immédiatement si une exécution planifiée a été manquée (ex. : système éteint) |
WantedBy=timers.target | Nécessaire pour que systemctl enable fonctionne |
Étape 3 : Activer et démarrer
sudo systemctl daemon-reload
sudo systemctl enable --now daily-cleanup.timer
Étape 4 : Vérifier
systemctl list-timers daily-cleanup.timer
Sortie :
NEXT LEFT LAST PASSED UNIT ACTIVATES
Wed 2025-12-24 02:00:00 UTC 10h left n/a n/a daily-cleanup.timer daily-cleanup.service
Testez le service manuellement pour confirmer son bon fonctionnement :
sudo systemctl start daily-cleanup.service
journalctl -u daily-cleanup.service --no-pager -n 20
Comprendre la syntaxe OnCalendar
La directive OnCalendar utilise un format d’expression calendaire flexible :
JourDeLaSemaine Année-Mois-Jour Heure:Minute:Seconde
Voici les schémas les plus courants :
| Planification | Expression OnCalendar |
|---|---|
| Chaque jour à minuit | *-*-* 00:00:00 |
| Chaque lundi à 9h | Mon *-*-* 09:00:00 |
| Premier de chaque mois | *-*-01 00:00:00 |
| Toutes les 15 minutes | *-*-* *:00/15:00 |
| Jours ouvrés à 18h | Mon..Fri *-*-* 18:00:00 |
| Chaque 1er janvier et juillet | *-01,07-01 00:00:00 |
| Toutes les 2 heures | *-*-* 00/2:00:00 |
Vous pouvez valider les expressions avec systemd-analyze calendar :
systemd-analyze calendar "Mon..Fri *-*-* 09:00:00"
Original form: Mon..Fri *-*-* 09:00:00
Normalized form: Mon..Fri *-*-* 09:00:00
Next elapse: Mon 2025-12-29 09:00:00 UTC
(in UTC): Mon 2025-12-29 09:00:00 UTC
From now: 5 days left
C’est l’un des plus grands avantages par rapport à cron — vous pouvez vérifier votre expression de planification avant de la déployer.
Timers monotones : intervalles relatifs à un événement
Toutes les planifications ne sont pas basées sur l’horloge. Les timers monotones se déclenchent par rapport à un événement :
[Timer]
OnBootSec=5min
OnUnitActiveSec=1h
| Directive | Déclenchement |
|---|---|
OnBootSec | X temps après le démarrage |
OnStartupSec | X temps après le lancement de systemd |
OnUnitActiveSec | X temps après la dernière activation du timer |
OnUnitInactiveSec | X temps après la dernière fin du service |
C’est utile pour les contrôles de santé, la collecte de métriques ou toute tâche devant s’exécuter à intervalles réguliers indépendamment de l’heure réelle.
Exemple — exécuter un contrôle de santé toutes les 5 minutes, en commençant 1 minute après le démarrage :
[Unit]
Description=Periodic health check
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
AccuracySec=10s
[Install]
WantedBy=timers.target
Le paramètre AccuracySec=10s réduit la fenêtre de regroupement par défaut d’une minute, de sorte que votre timer se déclenche plus précisément toutes les 5 minutes.
Fonctionnalités avancées
Délai aléatoire
Empêchez plusieurs serveurs de solliciter la même ressource simultanément :
[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=900
Cela planifie la tâche entre 3h00 et 3h15 du matin, systemd choisissant un décalage aléatoire à chaque cycle de démarrage.
Contrôle des ressources
Puisque la tâche s’exécute en tant que service systemd, vous pouvez appliquer des limites de ressources :
[Service]
Type=oneshot
ExecStart=/usr/local/bin/heavy-report.sh
CPUQuota=50%
MemoryMax=512M
IOWeight=50
Nice=15
Cron n’a pas d’équivalent — vous devriez ajouter des appels à nice, ionice et ulimit dans chaque script.
Notification en cas d’échec
Déclenchez une alerte lorsqu’une tâche planifiée échoue :
[Unit]
Description=Database backup
OnFailure=notify-admin@%n.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/db-backup.sh
Créez le modèle de notification dans /etc/systemd/system/notify-admin@.service :
[Unit]
Description=Send failure alert for %i
[Service]
Type=oneshot
ExecStart=/usr/local/bin/send-alert.sh "Unit %i failed on %H"
Conversion des cron jobs en timers systemd
Voici une approche systématique pour migrer vos cron jobs existants.
Exemple d’entrée cron :
30 2 * * 1-5 /usr/local/bin/db-backup.sh
Cela exécute la sauvegarde à 2h30 du matin les jours ouvrés. Les unités systemd équivalentes :
# /etc/systemd/system/db-backup.service
[Unit]
Description=Database backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/db-backup.sh
# /etc/systemd/system/db-backup.timer
[Unit]
Description=Database backup on weekday nights
[Timer]
OnCalendar=Mon..Fri *-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
Correspondance rapide cron vers OnCalendar :
| Cron | OnCalendar |
|---|---|
0 * * * * (toutes les heures) | *-*-* *:00:00 |
*/5 * * * * (toutes les 5 min) | *-*-* *:00/5:00 |
0 0 * * 0 (hebdo dimanche) | Sun *-*-* 00:00:00 |
0 0 1 * * (mensuel) | *-*-01 00:00:00 |
@reboot | Utilisez OnBootSec=0 |
Après avoir créé les unités :
sudo systemctl daemon-reload
sudo systemctl enable --now db-backup.timer
# Verify
systemctl list-timers db-backup.timer
# Comment out the old cron entry
sudo crontab -e
Surveillance et débogage des timers
Lister tous les timers actifs
systemctl list-timers --all
Consulter les journaux du timer
journalctl -u daily-cleanup.service --since today
journalctl -u daily-cleanup.service --since "2025-12-20" --until "2025-12-23"
Déboguer un timer qui ne se déclenche pas
# Check timer status
systemctl status daily-cleanup.timer
# Verify the calendar expression
systemd-analyze calendar "*-*-* 02:00:00"
# Check for unit file errors
systemd-analyze verify /etc/systemd/system/daily-cleanup.*
# View all timers including inactive
systemctl list-timers --all --no-pager
Timers transitoires pour les tâches ponctuelles
Besoin d’exécuter quelque chose dans 30 minutes sans créer de fichiers d’unité ?
systemd-run --on-active=30min /usr/local/bin/one-time-task.sh
Ou à une heure précise :
systemd-run --on-calendar="2025-12-24 15:00:00" /usr/local/bin/holiday-report.sh
Résolution de Problèmes
Le timer affiche “n/a” pour NEXT : Le timer est chargé mais pas activé. Exécutez systemctl enable --now <nom>.timer.
Le service fonctionne mais le timer ne le déclenche pas : Assurez-vous que les noms de fichiers .timer et .service correspondent exactement. Vérifiez avec systemctl cat <nom>.timer s’il y a des fautes de frappe.
“Failed to parse calendar specification” : Votre syntaxe OnCalendar est incorrecte. Validez avec systemd-analyze calendar "votre expression".
Le timer se déclenche en retard : La valeur par défaut de AccuracySec est d’une minute. systemd regroupe les réveils pour économiser l’énergie. Définissez AccuracySec=1s si vous avez besoin de précision.
Les exécutions manquées ne sont pas rattrapées : Vous avez oublié Persistent=true dans la section [Timer].
Résumé
- Les timers systemd remplacent cron avec deux fichiers d’unité : un
.service(quoi exécuter) et un.timer(quand l’exécuter) OnCalendargère les planifications basées sur l’horloge ;OnBootSecetOnUnitActiveSecgèrent les temporisations par intervallesPersistent=truerattrape les exécutions manquées après un temps d’arrêtsystemd-analyze calendarvous permet de valider les expressions de planification avant le déploiement- La journalisation intégrée via
journalctlélimine le besoin de redirection de logs personnalisée - Le contrôle des ressources (
CPUQuota,MemoryMax) et les notifications d’échec vous offrent une fiabilité de niveau production - Chaque cron job peut être migré vers un timer systemd avec une correspondance de syntaxe simple
- Utilisez
systemd-runpour des tâches planifiées ponctuelles rapides sans créer de fichiers d’unité
Configurer les tâches Cron sous Linux | journalctl : Interroger et analyser les journaux système Linux | Gérer les services Linux avec systemctl