systemd (Français)/Timers (Français)
systemd est capable de réaliser une partie des fonctionnalités de cron depuis la version 197 et d'anacron à l'aide des options Persistent
et OnCalendar
depuis la version 212.
Unités Timer
Ces fichiers sont des unités systemd qui se terminent en .timer. Ce type de fichier suit les mêmes règles que les fichiers de configuration pour les unités.
La configuration spécifique d'un timer se trouve dans la partie [Timer]
. Il y a deux manières de définir quand le service sera activé:
- le temps est relatif à un point de départ. Les points de départ les plus courants sont le démarrage de la machine, en utilisant l'option
OnBootSec
ainsi que le moment ou le timer a été activé, dans ce cas il faut utiliserOnUnitActiveSec
. - le temps relatif au temps réel, en utilisant l'option
OnCalendar
.
Il faut donc choisir l'option qui correspond à vos besoins, cela dépend donc si vous voulez démarrer le service après chaque démarrage ou non.
Pour chaque fichier .timer, un service doit exister pour décrire l'unité à activer quand le timer s'active. Par défaut, un service portant le même nom que le timer (à l'exception du suffixe) sera actif. Un exemple basique serait de créer un foo.timer
pour activer un foo.service
.
Comme le service est démarré par l'unité timer, il n'est pas nécessaire d'écrire une section [Install]
dans le service correspondant. Vous ne devez pas activer le service, mais le timer qui activera le service. Par contre, les unités timer ont besoin d'une section [Install]
et doivent être activées par un timers.target
.
Consulter systemd.timer(5) pour une liste complète de toutes les options disponibles pour l'unité timer.
Pour consulter tous les timer actifs avec les détails, exécutez la commande suivante:
$ systemctl list-timers NEXT LEFT LAST PASSED UNIT ACTIVATES Thu 2014-07-10 19:37:03 CEST 11h left Wed 2014-07-09 19:37:03 CEST 12h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service Fri 2014-07-11 00:00:00 CEST 15h left Thu 2014-07-10 00:00:13 CEST 8h ago logrotate.timer logrotate.service
Exemples
Timer relatif à un point de départ
Supposons que vous vouliez démarrer un script de backup myBackup.service
une fois par semaine et ce service doit être démarré après chaque démarrage. Il faut tout d'abord écrire le service suivant:
/etc/systemd/system/myBackup.service
[Unit] Description=effectue une sauvegarde [Service] Nice=19 IOSchedulingClass=2 IOSchedulingPriority=7 ExecStart=/path/to/service/myBackup
ansi que l'unité correspondante:
/etc/systemd/system/myBackup.timer
[Unit] Description=effectue une sauvegarde hebdomadaire ainsi qu'après le démarrage de la machine [Timer] OnBootSec=15min # le service démarrera 15 minutes après le démarrage de la machine OnUnitActiveSec=1w # le service démarrera une fois par semaine, une semaine après la dernière activation du timer [Install] WantedBy=timers.target
Il faut ensuite activer et démarrer le timer. Cela créera un lien symbolique vers /etc/systemd/system/timers.target.wants/myBackup.timer
. Pour s'assurer que vos nouveaux timer et services sont activés:
$ systemctl status myBackup ● myBackup.service - effectue une sauvegarde Loaded: loaded (/etc/systemd/system/myBackup.service; static) Active: inactive (dead) since Wed 2014-07-09 10:27:45 CEST; 1h 8min ago Main PID: 22000 (code=exited, status=0/SUCCESS)
$ systemctl status myBackup.timer ● myBackup.timer - effectue une sauvegarde hebdomadaire ainsi qu'après le démarrage de la machine Loaded: loaded (/etc/systemd/system/myBackup.timer; enabled) Active: active (waiting) since Mon 2014-07-07 19:21:53 CEST; 1 day 16h ago
- Ce service est marqué inactif étant donné qu'il ne doit pas rester actif une fois que la sauvegarde a été effectuée. Ainsi il n'est pas nécessaire d'utiliser l'option
RemainAfterExit=yes
dans l'unité correspondante. - Le timer est indiqué en attente, car il attend la prochaine activation.
- Dans le cas où le service est gourmand en ressource, il est conseillé de démarrer le timer suffisamment de temps après le démarrage de la machine. Sinon le login et le démarrage de X peuvent être sérieusement ralentis.
Timer à la anacron
Il faut pour cela utiliser les directives OnCalendar
et Persistent
. Par exemple, pour un timer
hebdomadaire:
/etc/systemd/system/timer-weekly.timer
[Unit] Description=Weekly timer [Timer] # lisez le man systemd.timer(5) pour tout ce qui est disponible OnCalendar=weekly # Autoriser la persistence entre les reboot Persistent=yes Unit=<le nom de l'unit à lancer> [Install] WantedBy=<à vous de voir selon le service>
La notion de Persistent
permet de déclencher le timer
même si la date initialement prévue pour que le timer
ne se lance a été dépassée (machine éteinte ou en veille). Cela permet également aux timer
lents (annuels, mensuels) de se lancer sans avoir besoin d'un uptime d'un an ou un mois.
Evénements horaires, journaliers, mensuels, etc.
La méthode à utiliser pour obtenir la fonctionnalité de cron est à l'aide de timers qui déclenchent des targets. Tous les services qui ont besoin d'être activés une fois par heure, par exemple, peuvent être déclarés comme dépendance de ces targets. La méthode proposée est détaillée dans ce billet[dead link 2021-11-19 ⓘ].
Tout d'abord la création de certains répertoires est requise:
mkdir /etc/systemd/system/timer-{hourly,daily,weekly,monthly,yearly}.target.wants
Il faut adapter selon ses besoins. Ensuite il faut créer les fichiers nécessaires.
Evénements horaires
/etc/systemd/system/timer-hourly.timer
[Unit] Description=Hourly Timer [Timer] OnBootSec=5min OnCalendar=hourly Unit=timer-hourly.target [Install] WantedBy=basic.target
/etc/systemd/system/timer-hourly.target
[Unit] Description=Hourly Timer Target StopWhenUnneeded=yes
Evénements journaliers
/etc/systemd/system/timer-daily.timer
[Unit] Description=Daily Timer [Timer] OnCalendar=daily Persistent=true Unit=timer-daily.target [Install] WantedBy=basic.target
/etc/systemd/system/timer-daily.target
[Unit] Description=Daily Timer Target StopWhenUnneeded=yes
Evénements hebdomadaires
/etc/systemd/system/timer-weekly.timer
[Unit] Description=Weekly Timer [Timer] OnCalendar=weekly Persistent=true Unit=timer-weekly.target [Install] WantedBy=basic.target
/etc/systemd/system/timer-weekly.target
[Unit] Description=Weekly Timer Target StopWhenUnneeded=yes
Evénements mensuels
/etc/systemd/system/timer-monthly.timer
[Unit] Description=Monthly Timer [Timer] OnCalendar=monthly Persistent=true Unit=timer-monthly.target [Install] WantedBy=basic.target
/etc/systemd/system/timer-monthly.target
[Unit] Description=Monthly Timer Target StopWhenUnneeded=yes
Evénements annuels
/etc/systemd/system/timer-yearly.timer
[Unit] Description=Yearly Timer [Timer] OnCalendar=yearly Persistent=true Unit=timer-yearly.target [Install] WantedBy=basic.target
/etc/systemd/system/timer-yearly.target
[Unit] Description=Yearly Timer Target StopWhenUnneeded=yes
Ajouter un événement
Ajouter un service à ces targets consiste à le placer dans le bon répertoire wants
. Si vous voulez par exemple créer une tâche journalière, il faut créer un service pour systemd. Si on veut que le service foo.bar
soit activé une fois par jour, il faut créer le fichier suivant:
/etc/systemd/system/foo.service
[Unit] Description=Starts program bar Wants=timer-daily.timer [Service] User= # Utilisez cette ligne si vous savez ce que vous faites. Sinon effacez-la. Type= # Utilisez cette ligne si vous savez ce que vous faites. Sinon effacez-la. Nice=19 IOSchedulingClass=2 IOSchedulingPriority=7 ExecStart=/usr/bin/bar --option1 --option2 # Plus d'un ExecStart peuvent être utilisés si nécessaire [Install] WantedBy=timer-daily.target
Ensuite démarrez et activez les services.
Activer et démarrer le timer
systemctl enable timer-{hourly,daily,weekly,monthly,yearly}.timer systemctl start timer-{hourly,daily,weekly,monthly,yearly}.timer
Activation d'événements par rapport au calendrier
Si vous souhaitez activer un service par rapport à une date du calendrier, vous devez créer un nouveau timer et lui lier le service. Exemple:
/etc/systemd/system/foo.timer
[Unit] Description=foo timer [Timer] # Pour choisir le bon format, référez-vous aux pages de man systemd.time OnCalendar=Mon-Thu *-9-28 *:30:00 Persistent=true Unit=foo.service [Install] WantedBy=basic.target
Le service devra ensuite être créé de la même manière que pour les services à intervalle. Veuillez toutefois les mettre dans le répertoire /etc/systemd/system
.