Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

astuces:remplacer_cron_par_systemd [Le 27/10/2019 à 14:39] (Version actuelle)
minzord Déplacement dans Astuces
Ligne 1: Ligne 1:
 +======== Remplacer cron par systemd ========
  
 +Les versions récentes de [[http://www.freedesktop.org/wiki/Software/systemd/|systemd]] améliorent le lancement d'évènements selon des critères temporels. Ce tutoriel montre, pour un cas simple, comment remplacer **cron** par **systemd**.
 +
 +Pour apporter plus de précisions, ce tutoriel contient de nombreux liens vers [[http://www.freedesktop.org/software/systemd/man/|le manuel]] de **systemd**. N'hésitez pas à cliquer ! ;-)
 +
 +  * [[https://linuxfr.org/news/%C3%A9volutions-techniques-de-systemd|En savoir plus sur systemd]]
 +  * [[https://linuxfr.org/news/archlinux-utilise-desormais-systemd-par-defaut-pour-les-nouvelles-installations#toc_3|Listes (non exhaustive) des distributions utilisant systemd]]
 +
 +===== Situation initiale =====
 +
 +Chez moi, le répertoire **/etc/cron.d/** ne contient qu'un seul et unique fichier, nommé **0hourly** dont voici le contenu :
 +<code bash>$ cat /etc/cron.d/0hourly</code>
 +<code bash>SHELL=/bin/bash
 +PATH=/sbin:/bin:/usr/sbin:/usr/bin
 +MAILTO=root
 +00 * * * * root run-parts /etc/cron.hourly</code>
 +
 +La dernière ligne nous informe que **cron** exécute la commande
 +  $ run-parts /etc/cron.hourly
 +toutes les heures, et en tant que root((Pour information : la commande **run-parts /etc/cron.hourly** lance tous les scripts contenus dans le répertoire /etc/cron.hourly/. Il n'y a qu'un seul script dans ce répertoire, qui se charge de lancer anacron. Celui-ci est configuré (via son fichier de configuration /etc/anacrontab) pour lancer des programmes de façon quotidienne, hebdomadaire ou mensuelle.)).
 +
 +Il n'y a pas d'autre fichier que **0hourly** dans le répertoire **/etc/cron.d/** ; nous en déduisons que, sur ma machine, **cron** ne sert qu'à une chose : lancer une commande toutes les heures. Pour ce cas simple, voyons comment remplacer **cron** par **systemd**.
 +
 +
 +===== Stopper et désactiver cron =====
 +
 +Pour commencer, nous [[http://www.freedesktop.org/software/systemd/man/systemctl.html#stop%20NAME...|stoppons]] **cron** :
 +  $ systemctl  stop   cronie.service
 +et nous [[http://www.freedesktop.org/software/systemd/man/systemctl.html#disable%20NAME...|désactivons]] le lancement automatique de **cron** au démarrage de l'ordinateur :
 +  $ systemctl disable cronie.service
 +//Remarque : parler de « démarrage de l'ordinateur » est un abus de langage. En fait, nous stoppons le lancement automatique de **cron** dans les cibles (les « target ») où il est lancé automatiquement. Les cibles sont, sous **systemd**, l'équivalent des niveaux d'exécution de **SysVinit**. La principale différence est que __plusieurs__ cibles de **systemd** peuvent être actives simultanément.//
 +
 +===== Créer une première unité systemd : un fichier .service =====
 +
 +Le paramétrage de systemd se fait par l'intermédiaire de fichiers textes : [[http://www.freedesktop.org/software/systemd/man/systemd.unit.html|les unités systemd]].
 +
 +Le gestionnaire de paquets installe ces unités dans le répertoire **/lib/systemd/system/** Comme les fichiers de ce répertoire sont susceptibles d'être modifiés ou effacés lors des mises-à-jour, il nous faut créer nos unités systemd dans un autre répertoire, réservé à l'administrateur et protégé des mises-à-jour. Ainsi, c'est le répertoire **/etc/systemd/system/** qui est notre terrain de jeu. :-D
 +
 +Dans un premier temps, nous créons un fichier **[[http://www.freedesktop.org/software/systemd/man/systemd.service.html|.service]]** qui décrit la commande que l'on souhaite lancer. Appelons ce fichier **taches-horaires.service** voici son contenu :
 +<code bash>$ cat /etc/systemd/system/taches-horaires.service</code>
 +<code bash>[Unit]
 +Description=Exécution des tâches horaires
 +
 +[Service]
 +ExecStart=/usr/bin/run-parts /etc/cron.hourly
 +User=root
 +Type=forking</code>
 +
 +La [[http://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=|ligne ExecStart=]] indique la commande à lancer. Il est nécessaire de préciser le chemin complet du programme, avec le « /usr/bin/ » devant. La [[http://www.freedesktop.org/software/systemd/man/systemd.exec.html#User=|ligne User=]] précise sous quel utilisateur lancer la commande, et la ligne [[http://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=|Type=]] décrit le type de processus.
 +
 +//Il existe de très nombreux paramètres pour configurer les unités systemd. Les principales sont expliquées dans les pages de manuel [[http://www.freedesktop.org/software/systemd/man/systemd.unit.html|systemd.unit]], [[http://www.freedesktop.org/software/systemd/man/systemd.service.html|systemd.service]] et [[http://www.freedesktop.org/software/systemd/man/systemd.exec.html|systemd.exec]].//
 +
 +Notre unité **.service** décrit parfaitement la commande que l'on souhaite lancer, mais elle ne contient pas le critère temporel « toutes les heures ». Pour cela, nous créons une seconde unité systemd : un « fichier horloge » **[[http://www.freedesktop.org/software/systemd/man/systemd.timer.html|.timer]]**
 +
 +===== Créer une seconde unité systemd : un fichier .timer =====
 +
 +Toujours dans le répertoire **/etc/systemd/system/**, nous créons le fichier **horloge-taches-horaires.timer** Il s'agit d'un « fichier horloge » **.timer** qui précise le caractère « toutes les heures » du lancement de l'unité **.service** créée précédemment. Le contenu de ce fichier **.timer** est :
 +
 +<code bash>$ cat /etc/systemd/system/horloge-taches-horaires.timer</code>
 +<code bash>[Unit]
 +Description=Horloge pour lancer "taches-horaires.service" toutes les heures
 +
 +[Timer]
 +Unit=taches-horaires.service
 +OnCalendar=*-*-* *:00:00
 +
 +[Install]
 +WantedBy=multi-user.target</code>
 +
 +Le paramètre [[http://www.freedesktop.org/software/systemd/man/systemd.timer.html#Unit=|Unit=]] indique quelle unité systemd doit être lancée((Le paramètre Unit= de notre unité **.timer** indique quelle unité **.service** doit lancer notre unité **.timer**. Si ce paramètre n'est pas renseigné, l'unité **.timer** lancera l'unité **.service** de même préfixe. Par exemple, //tartempion//**.timer** lancera //tartempion//**.service** (si //tartempion//**.service** existe, évidemment.) )). Le paramètre [[http://www.freedesktop.org/software/systemd/man/systemd.timer.html#OnCalendar=|OnCalendar=]] précise les critères temporels du lancement. Sa syntaxe est **AAAA-MM-JJ hh:mm:ss** (il est également possible d'utiliser les jours de la semaine, des précisions [[http://www.freedesktop.org/software/systemd/man/systemd.time.html#Calendar%20Events|sur ce lien]]).
 +
 +Grâce à notre unité **.timer**, notre première unité **.service** sera lancée tous les jours et toutes les heures, à zéro minute et zéro seconde.
 +
 +Le paramètre [[http://www.freedesktop.org/software/systemd/man/systemd.unit.html#WantedBy=|WantedBy=multi-user.target]] sera abordé plus bas.
 +
 +===== Mettre à jour systemd =====
 +
 +Pour que systemd tienne compte des deux nouvelles unités que nous venons de créer, on [[http://www.freedesktop.org/software/systemd/man/systemctl.html#daemon-reload|recharge]] la configuration de systemd :
 +  $ systemctl daemon-reload
 +
 +
 +===== Lancer et activer notre unité .timer =====
 +
 +Ouvrons un autre terminal, et utilisons-le pour suivre [[http://www.freedesktop.org/software/systemd/man/journalctl.html|le journal des évènements]] de systemd :
 +  $ journalctl -f
 +En cas de problème, les messages fournis par le journal des évènements sont intéressants (pour quitter : touches **Control+C**).
 +
 +À présent, [[http://www.freedesktop.org/software/systemd/man/systemctl.html#start%20NAME...|lançons]] notre unité **.timer** :
 +  $ systemctl start  horloge-taches-horaires.timer
 +
 +Nous n'avons pas besoin de lancer l'unité **.service** : c'est l'unité **.timer** qui se chargera de la démarrer toutes les heures.
 +
 +Activons [[http://www.freedesktop.org/software/systemd/man/systemctl.html#enable%20NAME...|le lancement automatique]] de notre unité **.timer** :
 +  $ systemctl enable horloge-taches-horaires.timer
 +C'est ici qu'entre en jeu le paramètre [[http://www.freedesktop.org/software/systemd/man/systemd.unit.html#WantedBy=|WantedBy=multi-user.target]] vu précédemment : notre unité **.timer** sera maintenant lancée automatiquement lorsqu'on activera la cible **multi-user.target**, ce qui est le cas à chaque démarrage //(si la cible **multi-user.target** ne s'active pas au démarrage, c'est que vous avez bidouillé, et que vous savez ce que vous faites ^_^)//
 +
 +//Remarque : le lancement automatique de l'unité se traduit par la création d'un lien symbolique dans le répertoire **/etc/systemd/system/multi-user.target.wants/** qui pointe vers notre unité **.timer**//
 +
 +===== Épilogue =====
 +
 +Après plusieurs jours, nous vérifions le bon fonctionnement de nos deux unités en consultant [[http://www.freedesktop.org/software/systemd/man/journalctl.html#-u|le journal des évènements]] de systemd :
 +  $ journalctl -u taches-horaires.service
 +  $ journalctl -u horloge-taches-horaires.timer
 +(pour quitter : touche **q**)
 +
 +===== Conclusion =====
 +
 +Pour un cas simple, nous avons remplacé **cron** par **systemd**. Nous avons d'abord créé une unité **.service** qui décrit la commande à lancer, puis une seconde unité **.timer** qui précise quand lancer l'unité **.service**
 +
 +Cette méthode est-elle généralisable à des cas plus complexes ? La pierre angulaire de cette méthode est le paramètre [[http://www.freedesktop.org/software/systemd/man/systemd.timer.html#OnCalendar=|OnCalendar=]] de l'unité **.timer**, qui indique quand agir. [[http://www.freedesktop.org/software/systemd/man/systemd.time.html#Calendar%20Events|Sa syntaxe]] couvre de nombreux cas, aussi il est certainement possible de généraliser cette méthode, et de remplacer totalement **cron** par **systemd**.
 +
 +Systemd permet également de lancer des unités selon des contraintes temporelles plus fines, par exemple : toutes les semaines **et** cinq minutes après le démarrage de l'ordinateur. Plus d'info [[http://www.freedesktop.org/software/systemd/man/systemd.timer.html#OnActiveSec=|sur ce lien]].
 +
 +Notons toutefois que **systemd** ne peut pas, à l'heure actuelle, remplacer **anacron**. En effet, **systemd** perd l'information « date de la dernière activation de l'unité machin » lors d'un arrêt de l'ordinateur. Voir [[http://lists.freedesktop.org/archives/systemd-devel/2013-February/008661.html|cette question]] et [[http://lists.freedesktop.org/archives/systemd-devel/2013-February/008697.html|la réponse apportée]]. Cette fonctionnalité arrivera peut-être dans une version future … En attendant, nous devrons nous contenter d'**anacron** pour les tâches
 +planifiées sur des ordinateurs qui ne sont pas allumés en permanence.
 +
 +===== Licence de ce tutoriel =====
 +Ce tutoriel est publié sous la licence [[http://www.wtfpl.net/|« Do What the Fuck You Want to Public License »]].
 +
 +[[http://www.wtfpl.net|{{ :logo_wtfpl.png | Logo « Do What the Fuck You Want to Public License »}}]]
 +
 +
 +===== Ajout de juin 2014 : l'option Persistent= =====
 +
 +> Notons toutefois que systemd ne peut pas, à l'heure actuelle, remplacer anacron. En effet, systemd perd l'information « date de la dernière activation de l'unité machin » lors d'un arrêt de l'ordinateur.
 +
 +Cela a changé récemment : depuis [[http://lists.freedesktop.org/archives/systemd-devel/2014-March/018232.html|sa version 212]], systemd offre l'option [[http://www.freedesktop.org/software/systemd/man/systemd.timer.html#Persistent=|Persistent=]] qui enregistre sur le disque dur la date de dernière exécution du service associé au **timer**. Ainsi, même lorsque l'ordinateur a été redémarré, systemd connaît la date de la dernière activation de l'unité.
 +
 +Pour un service démarré périodiquement (c'est le cas qui nous intéresse ici) : si une occurrence du service n'a pas été démarrée au moment prévu parce que l'ordinateur était éteint à ce moment-là, le service sera lancé au prochain démarrage de l'ordinateur.
 +
 +Voici deux exemples d'unité **timer** utilisant l'option [[http://www.freedesktop.org/software/systemd/man/systemd.timer.html#Persistent=|Persistent=]] :
 +
 +<code bash>$ cat /lib/systemd/system/updatedb.timer</code>
 +<code bash>[Unit]
 +Description=Lancement quotidien de l'unité updatedb.service
 +
 +[Timer]
 +Unit=updatedb.service
 +OnCalendar=daily
 +Persistent=true</code>
 +
 +
 +<code bash>$ cat /etc/systemd/system/mon-ntpd-personnel.timer</code>
 +<code bash>[Unit]
 +Description=Lancement hebdomadaire de l'unité mon-ntpd-personnel.service
 +
 +[Timer]
 +Unit=mon-ntpd-personnel.service
 +OnCalendar=weekly
 +Persistent=true
 +AccuracySec=12h
 +
 +[Install]
 +WantedBy=multi-user.target</code>
 +
 +Remarque : pour en savoir plus sur l'option [[http://www.freedesktop.org/software/systemd/man/systemd.timer.html#AccuracySec=|AccuracySec=]].
 +
 +L'option [[http://www.freedesktop.org/software/systemd/man/systemd.timer.html#Persistent=|Persistent=]] permet de déclencher des évènements périodiques, y compris pour des machines qui ne sont pas allumées en permanence. Systemd peut maintenant remplacer anacron.
 
astuces/remplacer_cron_par_systemd.txt · Dernière modification: Le 27/10/2019 à 14:39 par minzord     Haut de page
Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki Design by Chirripó