Pourquoi automatiser les tâches sur un VPS ?
Un VPS est un serveur qui tourne en continu, souvent sans supervision humaine directe. C'est précisément pour cela que l'automatisation des tâches récurrentes est fondamentale : personne ne sera là à 3 h du matin pour lancer la sauvegarde ou renouveler le certificat Let's Encrypt. Une tâche oubliée peut se traduire par une perte de données, un certificat expiré qui met le site hors ligne, ou un disque saturé faute de rotation des logs. Les deux grands outils disponibles sur Linux — cron et systemd timers — permettent de planifier ces opérations de façon fiable. Avant de choisir, encore faut-il comprendre ce que chacun apporte réellement.
Cas d'usage typiques sur un VPS
- Sauvegardes — dump MySQL ou PostgreSQL, archivage de fichiers vers un stockage distant
- Renouvellement de certificats TLS —
certbot renewouacme.sh --cronplanifiés deux fois par jour - Rotation et purge des logs — suppression des fichiers de plus de 30 jours, compression hebdomadaire
- Sondes de santé — vérification qu'un service écoute, redémarrage automatique si besoin
- Synchronisation de données —
rsyncvers un second nœud, mise à jour de caches - Nettoyage d'environnements — suppression de sessions expirées, vidage de répertoires temporaires
cron : rappel rapide
Cron est présent sur quasiment tous les systèmes Linux. Pour planifier une tâche, on édite la crontab de l'utilisateur courant avec crontab -e. La syntaxe repose sur cinq champs séparés par des espaces : minute, heure, jour du mois, mois, jour de la semaine, suivis de la commande. Par exemple, 0 3 * * * /usr/local/bin/backup.sh exécute le script tous les jours à 3 h. Les fichiers déposés dans /etc/cron.d/ appartiennent au système et peuvent spécifier l'utilisateur d'exécution directement dans la ligne. La sortie standard et l'erreur sont envoyées par mail à l'utilisateur — ce qui est souvent ignoré en pratique — ou redirigées manuellement vers un fichier. Cron ne conserve aucun historique natif des exécutions passées et ne gère pas les tâches manquées si la machine était éteinte.
systemd timers : introduction
Un timer systemd est une paire de deux fichiers unitaires : un fichier .service qui décrit quoi exécuter, et un fichier .timer qui décrit quand le lancer. Le timer est activé par systemctl enable --now monservice.timer et piloté par le gestionnaire de services, exactement comme n'importe quel service systemd. La directive OnCalendar= accepte une syntaxe riche : daily, Mon *-*-* 03:00:00, *:0/15 (toutes les 15 minutes). On peut aussi utiliser OnBootSec= et OnUnitActiveSec= pour des délais relatifs au démarrage ou à la dernière exécution. Toutes les sorties passent par journald et sont consultables via journalctl -u monservice.service. La commande systemctl list-timers affiche la liste de tous les timers actifs, leur prochaine échéance et la date de leur dernière activation.
cron vs systemd timers : tableau comparatif
| Critère | cron | systemd timer |
|---|---|---|
| Syntaxe de planification | 5 champs `* * * * *` | `OnCalendar=` lisible (`daily`, `Mon 03:00`) |
| Logs | Sortie mail ou redirection manuelle | journald natif, `journalctl -u` |
| Tâches manquées (machine éteinte) | Perdues (sauf `anacron`) | Persistent=true rejoue après redémarrage |
| Dépendances inter-services | Aucune | `After=`, `Requires=`, `Wants=` |
| Isolation et ressources | Hérite de l'env shell | Cgroups, `MemoryMax=`, `CPUQuota=` |
| Exécution en tant qu'utilisateur précis | Champ user dans `/etc/cron.d/` | `User=` et `Group=` dans le `.service` |
| Débogage | Difficile sans log | `systemctl status`, `journalctl -xe` |
| Disponibilité | Tous systèmes Unix | Systèmes avec systemd (Debian, Ubuntu, RHEL…) |
Quand conserver cron ?
Cron reste le bon choix dans plusieurs situations. Sur des systèmes anciens ou minimalistes sans systemd — certains conteneurs, BSD, images Alpine — cron est souvent le seul outil disponible. Dans un environnement multi-utilisateurs où chaque utilisateur gère ses propres tâches via crontab -e, cron est plus simple à déléguer sans accorder de droits root. Pour des scripts très simples à ligne unique, la crontab reste lisible et maintenable sans créer deux fichiers unitaires. Enfin, si votre équipe est familière de cron et que les tâches fonctionnent sans problème depuis des années, la migration n'apporte pas forcément de valeur immédiate. Le critère décisif est la nécessité de logs, de dépendances ou de ressources contraintes.
Quand passer aux systemd timers ?
Les timers systemd s'imposent dès que la tâche dépasse le cadre d'une simple commande isolée. Vous avez besoin de journald pour tracer chaque exécution, ses sorties et son code de retour sans plomberie manuelle ? Systemd timers. Votre script de sauvegarde doit s'exécuter seulement après que PostgreSQL soit prêt (After=postgresql.service) ? Systemd timers. Vous voulez limiter la mémoire d'un job de synchronisation pour qu'il n'étouffe pas les autres processus (MemoryMax=512M) ? Systemd timers. Et si le serveur redémarre à 2 h 58 alors que la sauvegarde de 3 h aurait dû tourner, Persistent=true garantit qu'elle s'exécutera au prochain démarrage.
Créer un timer systemd from scratch (exemple : sauvegarde quotidienne)
Créer le fichier service
Ouvrez /etc/systemd/system/backup.service et saisissez : [Unit], Description=Sauvegarde quotidienne PostgreSQL, After=postgresql.service, puis [Service], Type=oneshot, User=postgres, ExecStart=/usr/local/bin/backup.sh. Le type oneshot indique que le service se termine après l'exécution du script.
Créer le fichier timer
Créez /etc/systemd/system/backup.timer avec : [Unit], Description=Déclencheur quotidien pour la sauvegarde, puis [Timer], OnCalendar=*-*-* 03:00:00, Persistent=true, et [Install], WantedBy=timers.target.
Recharger systemd et activer le timer
Exécutez systemctl daemon-reload pour que systemd prenne en compte les nouveaux fichiers, puis systemctl enable --now backup.timer pour activer et démarrer immédiatement le timer.
Vérifier le timer
Tapez systemctl list-timers --all pour voir votre timer avec sa prochaine et sa dernière date d'exécution. Utilisez systemctl status backup.timer pour l'état du timer, et systemctl status backup.service pour le résultat de la dernière exécution.
Consulter les logs
Accédez à toutes les sorties du service avec journalctl -u backup.service pour l'historique complet, ou journalctl -u backup.service -n 50 --since today pour les 50 dernières lignes du jour.
Migrer une tâche cron existante vers systemd
Identifier la tâche cron à migrer
Listez vos crontabs avec crontab -l (utilisateur courant) et cat /etc/cron.d/* (système). Notez la commande exacte, l'utilisateur d'exécution, et le planning en cinq champs. Par exemple : 30 2 * * 1 root /usr/bin/certbot renew --quiet signifie chaque lundi à 2 h 30 en tant que root.
Traduire le planning en OnCalendar
Le format OnCalendar= de systemd s'écrit DayOfWeek Year-Month-Day Hour:Minute:Second. 30 2 * * 1 devient Mon *-*-* 02:30:00. Pour tester la traduction, utilisez systemd-analyze calendar 'Mon *-*-* 02:30:00' qui affiche les 10 prochaines occurrences calculées.
Créer les fichiers .service et .timer
Créez /etc/systemd/system/certbot-renew.service avec Type=oneshot, ExecStart=/usr/bin/certbot renew --quiet, et User=root. Créez ensuite /etc/systemd/system/certbot-renew.timer avec OnCalendar=Mon *-*-* 02:30:00 et Persistent=true. Exécutez systemctl daemon-reload && systemctl enable --now certbot-renew.timer.
Désactiver la ligne cron et valider
Commentez ou supprimez la ligne dans la crontab d'origine. Testez immédiatement avec systemctl start certbot-renew.service et consultez le résultat via journalctl -u certbot-renew.service -n 20. Vérifiez que le timer apparaît bien dans systemctl list-timers.
Pour une tâche devant s'exécuter quelques minutes après le démarrage puis régulièrement, combinez OnBootSec=5min et OnUnitActiveSec=1h dans le bloc [Timer]. Le job démarre 5 minutes après le boot, puis toutes les heures à partir de là — sans dépendre d'une heure d'horloge fixe.
Dépannage courant des timers systemd
Trois problèmes reviennent souvent lors de la mise en place des timers. Premier cas : le timer est actif mais ne se déclenche jamais. Vérifiez avec systemctl list-timers que la colonne NEXT affiche une date cohérente, et que systemctl status backup.timer indique active (waiting). Un daemon-reload oublié après modification d'un fichier unitaire est la cause numéro un. Deuxième cas : le service échoue silencieusement. Consultez journalctl -u monservice.service -n 50 — le code de retour et la sortie d'erreur y sont complets. Vérifiez que le chemin de l'ExecStart= est absolu. Troisième cas : la tâche ne rattrape pas les exécutions manquées. Assurez-vous que Persistent=true est bien présent dans le bloc [Timer].
Conclusion
Cron et systemd timers coexistent sans problème sur le même serveur — vous n'avez pas à tout migrer d'un coup. Conservez cron pour vos tâches simples et vos scripts utilisateur existants, et adoptez les timers systemd pour les nouvelles automatisations qui bénéficient des logs journald, des dépendances inter-services ou de l'isolation par cgroups. La commande systemd-analyze calendar et systemctl list-timers sont vos idéaux alliés pour valider et surveiller vos planifications.