Les systemd timers sont l’alternative moderne et plus puissante au cron classique sur Linux. Logging unifié via journalctl, dépendances entre services, gestion fine des erreurs, retry automatique. Pour les sysadmins en 2026 (informations vérifiées en avril 2026, susceptibles d’évoluer), c’est l’outil par défaut pour scheduling sur Linux.
Ce guide général couvre tout. Les articles connexes détaillent : systemd timers vs cron, créer un service systemd, journalctl logs, secrets et environnement.
Avantages systemd timers
- Logs unifiés via
journalctl -u job.service -f - Dépendances : timer attend qu’un autre service soit prêt
- Retry automatique sur échec
- Resource limits (CPU, RAM)
- Hardening intégré (NoNewPrivileges, ProtectSystem…)
- Persistent timers : exécutent même après reboot ou downtime
- OnCalendar syntax plus expressive que cron
Premier timer
# /etc/systemd/system/backup.service
[Unit]
Description=Daily backup
After=network.target
[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup.sh
StandardOutput=journal
StandardError=journal
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=600
[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now backup.timer
# Vérifier prochaine exécution
systemctl list-timers backup.timer
OnCalendar — syntaxe
OnCalendar=*-*-* 03:00:00— tous les jours à 03h00OnCalendar=Mon..Fri 09:00— lun-ven 09h00OnCalendar=*-*-01 00:00— premier jour du moisOnCalendar=hourly,daily,weekly,monthlyOnCalendar=*:0/15— toutes les 15 min
Persistent et catch-up
Persistent=true : si le serveur était down au moment prévu, le timer s’exécute au redémarrage. Critique pour backups quotidiens.
RandomizedDelaySec
Évite que tous vos VPS lancent leur backup à la même seconde. RandomizedDelaySec=600 = délai aléatoire 0-10 min.
Adaptation Afrique de l’Ouest
Pour les VPS PME africaines, systemd timers + Persistent garantit que les jobs backup tournent même après une coupure électrique ou perte connectivité (fréquent). Cron classique louperait ces fenêtres.
À lire ensuite
Pourquoi systemd timers remplacent cron sur un VPS Linux 2026
Sur un VPS Hostinger ou Contabo provisionne en 2026, vous heritez d un systeme dont l init est systemd. Les timers exposent trois capacites que cron n offre pas nativement : journalisation centralisee via journalctl, dependances entre unites, et calendrier OnCalendar plus expressif que crontab. Pour un freelance a Dakar qui automatise une sauvegarde nocturne d une boutique WooCommerce, basculer de cron vers un timer evite le piege classique du job qui echoue silencieusement parce que le PATH du shell cron n exporte pas NODE_OPTIONS.
La regle pratique : tout job recurrent qui depasse 30 secondes ou qui depend d un autre service (base de donnees, montage NFS, tunnel WireGuard) doit etre un timer systemd. Les vrais one-liners restent cron-friendly.
Etape 1 : creer l unite service qui execute la tache
Avant de planifier, il faut une unite .service qui sait executer la commande. Placez-la dans /etc/systemd/system/sauvegarde-woo.service. Le bloc [Service] declare Type=oneshot car la commande se termine apres execution, contrairement a un demon long-running.
[Unit]
Description=Sauvegarde nocturne base WooCommerce
After=network-online.target mariadb.service
Wants=network-online.target
[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/dump-woo.sh
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=5
Apres l ecriture, lancez systemctl daemon-reload puis testez la commande seule : systemctl start sauvegarde-woo.service. Si la commande retourne sans erreur et que journalctl -u sauvegarde-woo.service -n 50 montre un Code 0, l unite est saine. Un Code 1 ou 127 trahit en general un PATH absent ou un script non executable (chmod +x).
Etape 2 : ecrire le timer OnCalendar avec fenetre de derive
Le timer associe declenche le service. Le format OnCalendar utilise jour-de-semaine annee-mois-jour heure:minute:seconde. Pour une sauvegarde tous les jours a 02:30 heure du serveur, ecrivez OnCalendar=*-*-* 02:30:00. Ajoutez RandomizedDelaySec=1800 pour disperser la charge si plusieurs VPS du meme client demarrent leur sauvegarde simultanement.
[Unit]
Description=Planification sauvegarde nocturne WooCommerce
Requires=sauvegarde-woo.service
[Timer]
OnCalendar=*-*-* 02:30:00
RandomizedDelaySec=1800
Persistent=true
Unit=sauvegarde-woo.service
[Install]
WantedBy=timers.target
Activez avec systemctl enable –now sauvegarde-woo.timer. La directive Persistent=true rattrape une execution manquee si le serveur etait eteint a 02:30 ; le timer s execute des le demarrage suivant. C est crucial pour un VPS economique qui peut redemarrer pendant la fenetre de maintenance Hostinger.
Etape 3 : verifier la planification et le prochain declenchement
La commande systemctl list-timers –all liste tous les timers et leur prochain trigger. La colonne NEXT vous donne la date exacte du prochain run, LEFT le delta. Si NEXT affiche n a -, le timer est inactif ; relancez systemctl start. Pour un audit rapide, filtrez : systemctl list-timers sauvegarde-* affiche uniquement vos timers de sauvegarde.
Vous devriez obtenir apres activation : une ligne du type Wed 2026-05-06 02:30:00 WAT 14h left avec Activates: sauvegarde-woo.service. Cette ligne confirme que le calendrier est compris et que le service cible existe. Si systemd vous repond Failed to parse calendar specification, votre OnCalendar contient une faute de frappe (espace manquant entre la date et l heure typiquement).
Etape 4 : journaliser, debugger et alerter
Toute la sortie stdout/stderr de votre script atterrit dans le journal systemd. Consultez avec journalctl -u sauvegarde-woo.service –since today. Pour suivre en direct pendant un test : journalctl -u sauvegarde-woo.service -f. Les logs survivent aux reboots si Storage=persistent dans /etc/systemd/journald.conf, ce qui est le defaut sur Debian 12 et Ubuntu 24.04.
Pour etre alerte d un echec, ajoutez OnFailure=alerte-echec@%n.service dans le [Unit] du service surveille, puis creez alerte-echec@.service qui appelle un webhook Healthchecks.io ou Uptime Kuma. C est plus fiable que les mails MAILTO de cron qui finissent en spam chez OVH ou Orange Mail.
Etape 5 : migrer un crontab existant vers des timers
Listez vos jobs actuels avec crontab -l. Pour chaque ligne, identifiez la commande et l horaire. Une regle 30 2 * * * /usr/local/bin/dump-woo.sh devient l exemple ci-dessus. Pour un job toutes les 15 minutes, OnCalendar=*:0/15 remplace */15 * * * *. Pour un job hebdomadaire dimanche 04:00, OnCalendar=Sun *-*-* 04:00:00 remplace 0 4 * * 0.
Une fois le timer valide pendant 48 heures (verifier journalctl), commentez la ligne dans crontab -e plutot que la supprimer. Cela laisse une trace de migration. Apres une semaine sans regression, supprimez-la definitivement.
Etape 6 : limiter les ressources avec les directives de slice
Un avantage que cron n offre pas : limiter CPU, RAM et IO d un job via systemd. Sur un VPS 2 GB mutualise avec MySQL et PHP-FPM, une sauvegarde non bornee peut declencher l OOM killer. Ajoutez dans [Service] : MemoryMax=512M, CPUQuota=40%, TasksMax=128. Ces limites sont appliquees par cgroups v2, actif par defaut sur tout systemd recent.
Verifiez l application avec systemd-cgtop pendant l execution. Si votre script depasse MemoryMax, systemd le tue avec un signal SIGKILL et journalctl loggue Out of memory. Augmentez progressivement plutot que de retirer la limite.
Etape 7 : timers transient pour tests et tests ponctuels
Pour tester une planification sans creer de fichier permanent, systemd-run propose des timers transient. Exemple : systemd-run –on-calendar=’*:0/5′ –unit=test-ping.service /usr/bin/ping -c1 1.1.1.1 declenche un ping toutes les 5 minutes. Listez avec systemctl list-timers, supprimez avec systemctl stop test-ping.timer. Aucun fichier ne reste sur le disque.
Cette technique est ideale pour valider un nouveau script en production sans polluer /etc/systemd/system. Une fois le comportement confirme, materialisez l unite dans un fichier versionne avec votre infra-as-code.
Etape 8 : monitoring centralise des timers en flotte
Si vous gerez 5 VPS pour des clients differents a Abidjan, Lome ou Dakar, exportez l etat des timers vers Prometheus avec node_exporter et le collecteur systemd. La metrique node_systemd_timer_last_trigger_seconds vous indique combien de secondes se sont ecoulees depuis le dernier declenchement. Un timer qui n a pas tourne depuis 26 heures alors qu il est quotidien declenche une alerte Alertmanager.
Sur un angle proche, voyez notre guide Prometheus node-exporter VPS et notre comparatif Uptime Kuma vs Healthchecks pour boucler la chaine d alerting bout en bout.
Etape 9 : timers OnBootSec et OnUnitActiveSec pour cas non calendaires
Tous les besoins ne se traduisent pas en horaire fixe. OnBootSec=15min declenche le service 15 minutes apres le boot, utile pour reindexer un cache Redis apres redemarrage. OnUnitActiveSec=2h declenche le service 2 heures apres son dernier run reussi, equivalent d un job toutes les 2 heures glissantes. Combinez-les : OnBootSec=10min suivi de OnUnitActiveSec=6h pour un health-check qui demarre 10 min apres boot puis tourne toutes les 6 heures.
Cette flexibilite permet de modeliser des intervalles que cron ne sait pas exprimer naturellement, comme un retry exponentiel manuel ou un job qui se cale sur sa propre duree d execution.
Etape 10 : securite, isolation et hardening des unites
Un service qui tourne en root sans isolation est une surface d attaque. Ajoutez dans [Service] : ProtectSystem=strict, ProtectHome=true, PrivateTmp=true, NoNewPrivileges=true, CapabilityBoundingSet=. Pour un script de sauvegarde qui doit ecrire dans /var/backups, autorisez avec ReadWritePaths=/var/backups.
Verifiez l hardening avec systemd-analyze security sauvegarde-woo.service. Cette commande retourne un score de 0 a 10 (plus bas = mieux) et liste les directives manquantes. Un score sous 3.0 est considere comme correctement durci. Sur un VPS partage chez Hostinger, le score importe car une elevation de privilege via un script vulnerable peut compromettre les autres tenants si le kernel a une CVE non patchee.
Etape 11 : audit final, sauvegarde des unites et suite
Avant de cloturer la migration, sauvegardez /etc/systemd/system dans votre depot Git d infra. Un simple tar -czf systemd-units-$(date +%F).tar.gz /etc/systemd/system/*.service /etc/systemd/system/*.timer suffit. Documentez chaque timer dans un README : ce qu il fait, son horaire, son script cible, l alerte associee.
Lectures complémentaires sur le monitoring de ces taches, enchainez avec notre guide Prometheus node-exporter pour exposer les metriques systemd, et notre comparatif Uptime Kuma vs Healthchecks vs Statping vs Gatus pour choisir le service de heartbeat. Une fois l ensemble en place, votre flotte de VPS devient observable sans script bash maison.
Etape 12 : timers en chaine et dependances entre unites
Un avantage decisif sur cron : un timer peut declencher un service qui en declenche un autre via Wants= ou Requires=. Pour une routine de maintenance hebdomadaire qui enchaine vacuum PostgreSQL, reindexation Elasticsearch puis purge des logs, vous evitez d ecrire un mega-script bash fragile. Chaque etape est une unite isolee, journalisee separement, avec sa propre politique de retry.
Exemple concret : maintenance-hebdo.timer declenche maintenance-hebdo.service qui contient ExecStart=/bin/true et OnSuccess=vacuum-pg.service ; vacuum-pg.service definit OnSuccess=reindex-es.service ; reindex-es.service termine la chaine. Si une etape echoue, la chaine s arrete et OnFailure pointe vers votre webhook d alerte. Vous savez exactement quelle etape a casse, sans grep dans un log monolithique.
Etape 13 : timers utilisateur sans privilege root
Pour un developpeur qui veut planifier un script personnel sans demander le root au sysadmin, systemd propose les unites utilisateur. Placez vos fichiers dans ~/.config/systemd/user/, lancez systemctl –user daemon-reload puis systemctl –user enable –now mon-script.timer. Ces timers ne tournent que pendant les sessions utilisateur, sauf si vous activez loginctl enable-linger votre-user.
C est ideal pour automatiser une synchro rclone vers un Backblaze B2 ou un push git nightly d un repo personnel sur un VPS de freelance. Aucun privilege eleve, isolation naturelle dans le cgroup utilisateur, journalctl –user-unit mon-script.service pour les logs.
Etape 14 : pieges courants et erreurs frequentes
Premier piege : oublier daemon-reload apres modification d un fichier .timer ou .service. systemd continue d utiliser la version en memoire et vos changements semblent ignores. Reflexe systematique : apres toute edition, systemctl daemon-reload puis systemctl restart de l unite ciblee.
Deuxieme piege : un OnCalendar avec un fuseau implicite. systemd utilise le fuseau du serveur. Si votre VPS est en UTC mais que vous raisonnez en heure de Dakar (UTC+0) ou Abidjan (UTC+0), pas de probleme, mais un VPS provisionne par defaut en CET (UTC+1) decale vos sauvegardes d une heure. Verifiez avec timedatectl puis forcez avec timedatectl set-timezone Africa/Dakar si besoin.
Troisieme piege : un script qui suppose un shell interactif (alias, fonctions du .bashrc). Le service systemd n herite pas de votre environnement. Definissez explicitement Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin et toutes les variables necessaires dans le bloc [Service]. Sinon votre node, votre python venv ou votre composer ne sont pas trouves.
Etape 15 : aller plus loin avec systemctl edit
Plutot que d editer directement le fichier, systemctl edit sauvegarde-woo.timer cree un fichier override.conf qui surcharge uniquement les directives modifiees. Avantage : si vous mettez a jour le paquet qui fournit l unite originale, votre override survit. Pour repartir de l original, systemctl revert sauvegarde-woo.timer supprime le override en un clic.
Cette discipline d override est cruciale en production : on ne touche jamais aux unites livrees par un paquet. On les surcharge proprement, on les versionne, on les documente. Votre futur vous (ou le freelance qui reprend le serveur) vous remerciera.
Recapitulatif operationnel
En production, un timer systemd bien ecrit combine OnCalendar precis, Persistent=true pour rattrapage, RandomizedDelaySec pour eviter les pics, OnFailure pour l alerte, et hardening minimum (ProtectSystem, NoNewPrivileges, ReadWritePaths). Cette base couvre 95 pourcents des besoins d automatisation sur un VPS Hostinger ou Contabo et remplace avantageusement cron pour toutes les taches non triviales.