systemd/cron

De ArchwikiFR

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 utiliser OnUnitActiveSec.
  • 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:

Fichier: /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:

Fichier: /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
Note:
  • 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 :

Fichier: /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.

Note: La méthode qui suit est en cours de discussion, car elle est sujet à controverse. Consulter ce lien pour plus de détails.


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.

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

Fichier: /etc/systemd/system/timer-hourly.timer
[Unit]
Description=Hourly Timer

[Timer]
OnBootSec=5min
OnCalendar=hourly
Unit=timer-hourly.target

[Install]
WantedBy=basic.target
Fichier: /etc/systemd/system/timer-hourly.target
[Unit]
Description=Hourly Timer Target
StopWhenUnneeded=yes

Evénements journaliers

Fichier: /etc/systemd/system/timer-daily.timer
[Unit]
Description=Daily Timer

[Timer]
OnCalendar=daily
Persistent=true
Unit=timer-daily.target

[Install]
WantedBy=basic.target
Fichier: /etc/systemd/system/timer-daily.target
[Unit]
Description=Daily Timer Target
StopWhenUnneeded=yes

Evénements hebdomadaires

Fichier: /etc/systemd/system/timer-weekly.timer
[Unit]
Description=Weekly Timer

[Timer]
OnCalendar=weekly
Persistent=true
Unit=timer-weekly.target

[Install]
WantedBy=basic.target
Fichier: /etc/systemd/system/timer-weekly.target
[Unit]
Description=Weekly Timer Target
StopWhenUnneeded=yes


Evénements mensuels

Fichier: /etc/systemd/system/timer-monthly.timer
[Unit]
Description=Monthly Timer

[Timer]
OnCalendar=monthly
Persistent=true
Unit=timer-monthly.target

[Install]
WantedBy=basic.target
Fichier: /etc/systemd/system/timer-monthly.target
[Unit]
Description=Monthly Timer Target
StopWhenUnneeded=yes


Evénements annuels

Fichier: /etc/systemd/system/timer-yearly.timer
[Unit]
Description=Yearly Timer

[Timer]
OnCalendar=yearly
Persistent=true
Unit=timer-yearly.target

[Install]
WantedBy=basic.target
Fichier: /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:

Fichier: /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:

Fichier: /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.