EQVPS
Tableau de bordCommencer

Planifier des tâches sur un VPS avec cron et les timers systemd

Lancez sauvegardes, nettoyages et scripts selon un planning. Cron en cinq minutes avec les trois pièges qui cassent les tâches en silence, puis les timers systemd pour les journaux, le rattrapage après une coupure et l'heure exacte. Chaque comportement ci-dessous a été testé sur un serveur Ubuntu 24.04 neuf.

Un serveur se rentabilise en travaillant pendant que vous dormez : sauvegardes, rotation des journaux, renouvellement des certificats, un rapport à neuf heures. Linux a deux planificateurs pour cela. Cron a quarante ans et tient en une ligne. Les timers systemd demandent deux petits fichiers et apportent en échange les journaux, le rattrapage après une coupure et l'heure exacte. Ce guide couvre les deux sous Ubuntu 24.04, chaque comportement vérifié sur un serveur neuf issu de notre image, y compris les trois erreurs qui font échouer une tâche cron sans un mot.

Il vous faut un utilisateur avec sudo ; le guide d'installation d'Ubuntu en crée un.

1. Cron en cinq minutes

Cron est installé et actif sur nos images Ubuntu et Debian. Chaque utilisateur a une table de tâches ; modifiez la vôtre avec :

crontab -e

Chaque ligne contient cinq champs de temps et une commande :

# min hour day month weekday  command
  30  3    *   *     *        /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
  */5 *    *   *     *        /usr/local/bin/check.sh
  0   9    *   *     1-5      /usr/local/bin/report.sh
  @reboot                     /usr/local/bin/start-tunnel.sh

Soit : 03:30 chaque nuit, toutes les 5 minutes, 09:00 en semaine et une fois après chaque démarrage. */5 veut dire une valeur sur cinq, 1-5 une plage, 1,15 une liste. Le fuseau horaire du serveur s'applique, UTC sur nos images ; réglez le vôtre une fois avec le guide nom d'hôte et fuseau horaire et cron suit.

Vérifiez ce qui s'est exécuté avec journalctl -u cron. Chaque exécution journalise l'utilisateur et la commande, et c'est là que les trois pièges apparaissent.

Piège 1 : la sortie disparaît. Cron envoie la sortie d'une tâche par e-mail à l'utilisateur. Notre image n'a pas de serveur de messagerie, donc le journal indiquait (CRON) info (No MTA installed, discarding output) et la sortie était perdue. Redirigez-la vous-même, comme le premier exemple avec >> /var/log/backup.log 2>&1.

Piège 2 : le signe pourcentage. Dans une crontab, % termine la commande et transforme le reste en entrée standard. Nous avons planifié date +%F > /tmp/today. Le journal montre ce que cron a vraiment lancé : CMD (date +). Aucun fichier n'a été écrit et aucune erreur ne nous est parvenue. Écrivez \%, ou mettez la commande dans un script et planifiez le script.

Piège 3 : un environnement différent. Cron lance les tâches avec /bin/sh, pas bash, dans votre dossier personnel, avec un environnement réduit. Sous Ubuntu 24.04, le PATH valait mieux que sa réputation : le chemin système complet, /usr/local/bin et /snap/bin compris, pour root comme pour un utilisateur normal. Ce qui manque toujours, c'est tout ce qui se trouve dans votre dossier personnel : ~/.local/bin, le node de nvm, pipx, cargo. Utilisez des chemins complets dans la tâche, ou commencez la ligne par . $HOME/.profile;.

Les tâches qui appartiennent au système plutôt qu'à un utilisateur vont dans /etc/cron.d/, sous forme de fichier avec un champ en plus, l'utilisateur :

30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Ubuntu exécute aussi tout ce qui se trouve dans /etc/cron.hourly, cron.daily, cron.weekly et cron.monthly, à la 17e minute de chaque heure, à 06:25, à 06:47 le dimanche et à 06:52 le 1er du mois. Déposez-y un script exécutable et il tournera avec les autres.

2. Les timers systemd

Un timer, ce sont deux unités : un service qui fait le travail et un timer qui dit quand. Créez d'abord le script, puis les unités.

sudo nano /usr/local/bin/backup.sh
sudo chmod +x /usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run the backup every night at 03:30

[Timer]
OnCalendar=*-*-* 03:30
Persistent=true
AccuracySec=1m

[Install]
WantedBy=timers.target

Activez le timer, pas le service :

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer

list-timers montre la prochaine exécution, le temps restant et la dernière exécution. Les journaux ne demandent aucune configuration : journalctl -u backup.service contient chaque démarrage, chaque fin et chaque ligne de sortie, horodatés. Pour lancer la tâche tout de suite, sudo systemctl start backup.service ; c'est aussi ainsi qu'on teste le script avant de faire confiance au planning.

Syntaxe du calendrier. OnCalendar se lit jour-de-semaine année-mois-jour heure:minute:seconde, avec * pour n'importe quelle valeur. Testez une expression avant de l'utiliser :

systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2

La commande affiche la forme normalisée et les prochaines dates. Quelques expressions que nous avons vérifiées :

OnCalendarSignification
*-*-* 03:30Tous les jours à 03:30
Mon..Fri *-*-* 09:00En semaine à 09:00
*:0/15Toutes les 15 minutes
weeklyLe lundi à 00:00
*-*-01 04:00Le 1er de chaque mois à 04:00
*-*-* 03:00 Europe/Kyiv03:00 heure de Kyiv ; exécuté à 01:00 UTC chez nous

Les trois réglages à connaître. Persistent=true enregistre la dernière exécution sur le disque et rattrape une exécution manquée pendant que le serveur était éteint ou le timer arrêté. Nous avons arrêté notre timer toutes les deux minutes, attendu qu'une exécution prévue passe, puis l'avons relancé : l'exécution manquée est partie dans la même seconde. Sans Persistent, il attend simplement le créneau suivant.

AccuracySec est la surprise. Par défaut, systemd regroupe les timers dans une fenêtre d'une minute pour économiser les réveils, d'où notre première exécution à 07:42:18 et non 07:42:00. Avec AccuracySec=1s, les suivantes sont tombées à 07:46:00 et 07:48:00 à la seconde près. Réglez-le quand la minute compte ; gardez la valeur par défaut pour une sauvegarde nocturne.

RandomizedDelaySec=10m fait l'inverse, exprès : il étale le démarrage sur une fenêtre pour que dix serveurs ne frappent pas le même stockage de sauvegarde à la même seconde.

Pour une tâche ponctuelle, aucun fichier :

sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh

Cela crée un timer transitoire qui se déclenche une fois puis disparaît ; d'ici là, systemctl list-timers l'affiche.

3. Lequel choisir

CronTimer systemd
Mise en place1 ligne2 fichiers
JournauxSeulement si vous redirigez la sortiejournalctl -u name.service
Exécution manquée, serveur éteintPerdueLancée au démarrage avec Persistent=true
Tâche encore en cours au tic suivantUne seconde copie démarreIgnorée jusqu'à la fin de la première
Heure exacteÀ la minuteÀ la seconde avec AccuracySec=1s
ÉtatAucunlist-timers, systemctl status

Prenez cron pour une ligne rapide que vous reconnaîtrez dans un an. Prenez un timer pour tout ce dont vous devez voir l'échec, qui ne doit pas se chevaucher ou qui doit tourner après un redémarrage manqué : sauvegardes, renouvellement des certificats, nettoyage des bases de données. Si une tâche cron peut se chevaucher, enveloppez-la : flock -n /tmp/backup.lock /usr/local/bin/backup.sh, et la seconde copie s'arrête aussitôt.

Les deux planificateurs lancent une tâche et s'arrêtent. Pour un programme qui doit tourner en continu et revenir après un plantage, il faut un service, pas un planning ; voir comment créer un service systemd et, pour Windows, comment faire tourner un script 24/7 sur Windows Server. Un bon premier timer est celui de notre guide de sauvegarde avec restic ; les mises à jour de sécurité automatiques sont un timer qu'Ubuntu fournit déjà, apt-daily-upgrade.timer, l'un des 17 actifs sur un serveur neuf.

FAQ

Pourquoi ma tâche marche dans le terminal mais pas dans cron ?

Trois raisons habituelles. Cron lance la tâche avec sh, pas bash, donc la syntaxe propre à bash échoue. Les outils installés dans votre dossier personnel, comme nvm, pipx ou cargo, ne sont pas dans le PATH de cron : utilisez des chemins complets. Et tout % dans la ligne de commande termine la commande : date +%F est devenu date + sur notre serveur. Échappez-le en \% ou déplacez la commande dans un script.

Où va la sortie de cron ?

Par e-mail, par défaut. Notre image n'a pas de serveur de messagerie, donc cron journalise 'No MTA installed, discarding output' et la sortie est perdue. Ajoutez >> /var/log/myjob.log 2>&1 à la tâche, ou passez à un timer systemd, dont la sortie arrive automatiquement dans le journal.

Quel est l'avantage d'un timer systemd sur cron ?

Les journaux dans journalctl, pas de seconde copie d'une tâche encore en cours, le rattrapage avec Persistent=true des exécutions manquées pendant que le serveur était éteint, et une ligne d'état qui indique la prochaine et la dernière exécution. Cron gagne sur la concision : une ligne au lieu de deux fichiers.

Mon timer s'est déclenché 18 secondes en retard. Pourquoi ?

Par défaut, systemd regroupe les timers dans une fenêtre d'une minute pour économiser les réveils : c'est le réglage AccuracySec. Notre timer toutes les deux minutes s'est déclenché à 07:42:18 au lieu de 07:42:00. Avec AccuracySec=1s, il est parti à 07:46:00 pile. Réglez-le quand la minute exacte compte.

Quel fuseau horaire utilisent cron et les timers ?

Celui du serveur, UTC sur nos images. Réglez-le une fois avec timedatectl, voir notre guide sur le nom d'hôte et le fuseau horaire, et cron comme les timers le suivent. Un timer peut aussi avoir son propre fuseau : OnCalendar=*-*-* 03:00 Europe/Kyiv s'est exécuté à 01:00 UTC dans notre test.

Commentaires

Pas encore de commentaires. Soyez le premier.

Laisser un commentaire

Les commentaires sont modérés avant leur publication.