SystemD: Démarrage automatique d'un script python sur Raspberry-Pi 3

Dans un très vieille article "Lcd Order track - Détecter les nouvelles commandes PrestaShop avec un Raspberry-Pi" nous utilisions un script Python sur un Pi-B (jusque hier... 3 ans de bons et loyaux services).
Un script qui démarrait au boot.
Version Original Lcd Order Track

Nous venons de faire un upgrade matériel et logiciel puisque nous venons de passer sous Raspbian Jessie.

Raspbian Jessie = SystemD
Avec Raspbian Jessie (Pi 2 et Pi 3), c'est SystemD qui est utilisé pour la gestion des services et démarrage automatique.

Je dois avouer que la configuration du démarrage de lcdordertrack.py fût plus facile qu'attendu!

Je vous recommande chaudement les lectures suivantes (source d'information utiles pour systemD et le démarrage d'un script python depuis systemD.

Voici, en quelques étapes, les opérations effectuées pour démarrer automatiquement le script lcdordertrack.py

Déclarer le service (une unité/unit)
sudo nano /lib/systemd/system/lcdordertrack.service


Et y ajouter le contenu suivant:

[Unit]
Description=MCHobby LCD Order Tracker
After=multi-user.target

[Service]
Type=idle
ExecStart=/usr/bin/python /home/pi/PrestaConsole/lcdordertrack.py > /home/pi/lcdordertrack.log 2>&1

[Install]
WantedBy=multi-user.target

Utiliser la combinaison de touche CTRL-X, Y pour quitter nano en sauvant le fichier.

Vous noterez que nous avons ajouté des redirections (sortie standard et sortie erreur) vers des fichiers de log.

Permission sur le service (l'unité)
Un point vraiment important est de ficher correctement les permissions sur notre nouveau fichier!

sudo chmod 644 /lib/systemd/system/myscript.service


Activer le service (unité) dans SystemD

sudo systemctl daemon-reload
sudo systemctl enable myscript.service


La deuxième ligne va créer un lien symbolique (propre au système) qui activera le service au prochain démarrage.

Le plus facile maintenant est encore de faire un
sudo reboot

Eviter les pièges - Utilisateur vs SystemD
En utilisant un script python, vous devez garder à l'esprit qu'il n'utilise pas votre "login" courant pour fonctionner.

Donc, ce qui est valable en session interactive ne le sera pas forcément lorsqu'il sera exécuté avec SystemD (le processus parent sera SystemD, donc avec un PID = 1)

Par exemple, si vous chargez un fichier "ini", vous devrez spécifier le chemin complet du fichier ini (alors qu'il est simplement chargé depuis le répertoire courant si vous lancez votre script à la main dans un shell).

Etat du service et instructions utiles

Il arrive souvent que cela ne fonctionne pas la première fois, c'est qu'utiliser un service à certaines contraintes (droit accès, sécurité sur les fichiers comme sur le GPIO par exemple, accès à certaines ressources.

Nous avons prévu des fichiers de log dans dans la commande de démarrage ( /home/pi/lcdordertrack.log ), utile pour récupérer les informations produites par l'instruction print().

SystemD produit également de nombreuses informations utiles avec l'option status .

sudo systemctl status lcdordertrack.service

ce qui avait produit ce résultat très intéressant:

● lcdordertrack.service - MCHobby LCD Order Tracker
   Loaded: loaded (/lib/systemd/system/lcdordertrack.service; enabled)
   Active: failed (Result: exit-code) since Sat 2016-10-29 10:38:13 UTC; 2min 45s ago
  Process: 636 ExecStart=/usr/bin/python /home/pi/PrestaConsole/lcdordertrack.py > /home/pi/lcdordertrack.log 2>&1 (code=exited, status=1/FAILURE)
 Main PID: 636 (code=exited, status=1/FAILURE)

Oct 29 10:38:13 r1501 python[636]: Traceback (most recent call last):
Oct 29 10:38:13 r1501 python[636]: File "/home/pi/PrestaConsole/lcdordertrack.py", line 39, in 
Oct 29 10:38:13 r1501 python[636]: config = Config()
Oct 29 10:38:13 r1501 python[636]: File "/home/pi/PrestaConsole/config.py", line 34, in __init__
Oct 29 10:38:13 r1501 python[636]: self._presta_api_key = config.get( CONFIG_SECTION_PRESTAAPI, CONFIG...KEY )
Oct 29 10:38:13 r1501 python[636]: File "/usr/lib/python2.7/ConfigParser.py", line 607, in get
Oct 29 10:38:13 r1501 python[636]: raise NoSectionError(section)
Oct 29 10:38:13 r1501 python[636]: ConfigParser.NoSectionError: No section: 'PRESTA-API'
Oct 29 10:38:13 r1501 systemd[1]: lcdordertrack.service: main process exited, code=exited, status=1/FAILURE
Oct 29 10:38:13 r1501 systemd[1]: Unit lcdordertrack.service entered failed state.
Hint: Some lines were ellipsized, use -l to show in full.

Où nous pouvions voir qu'il y avait un problème avec config.py (et donc la lecture de notre config.ini).

sudo systemctl start lcdordertrack.service

permet de démarrer le service après modification ou ajustement.
Vous avez également l'opportunité d'utiliser les commandes start, stop et restart. Les commandes enable et disable permettent respectivement d'activer et désactiver un service.