Rasp-AutoStart-Script

De MCHobby - Wiki
Révision datée du 9 février 2018 à 09:42 par Admin (discussion | contributions) (→‎Ressources utiles)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Sauter à la navigation Sauter à la recherche


MCHobby investit du temps et de l'argent dans la réalisation de traduction et/ou documentation. C'est un travail long et fastidieux réalisé dans l'esprit Open-Source... donc gratuit et librement accessible.
SI vous aimez nos traductions et documentations ALORS aidez nous à en produire plus en achetant vos produits chez MCHobby.

Introduction

Si vous lisez cette page c'est probablement parce que vous avez besoin de démarrer automatiquement un script python au démarrage de votre Pi.

Garder bien à l'esprit les éléments suivants qui peuvent largement influencer le démarrage ou non de votre script:

  1. Si vous avez une interface utilisateur, l'utilisateur qui lancera le script doit pouvoir accéder au terminal!
  2. Si vous utilisez des ressources particulières (eg: le GPIO), l'utilisateur qui lancera votre script doit posséder les droits adéquats.

System V vs System D

  • Raspbian Wheezy (et prédécesseurs) utilise un système d'initialisation basé sur System V, ses RunLevels et scripts shell d'initialisations.
  • Depuis Raspbian Jessie (courant 2016), le système d'initialisation est basé sur le très controversé SystemD (Wikipedia.fr)

Suivant la version de Rapsbian, vous pourrez utiliser une méthode où une autre.

Avec System V

Utilisable jusqu'à Raspbian Whezzy, le système d'initialisation basé sur des RunLevels et des scripts.

System V permet d'insérer facilement le lancement d'un script... mais malheureusement, ce système est remplacé par SystemD (nettement moins transparent).

Si vous avez besoin de démarrer un script sous System V, vous pouvez consulter notre "tutoriel Init-Script pour écran LCD"

Avec System D

SystemD (Wikipedia.fr) est apparu depuis Raspbian Jessie.

Notre expérience personnelle de SystemD n'a pas été des plus réjouissantes... dans les faits, installer une horloge temps réel sur le Pi s'est révéler être un cauchemar de configuration (et il reste encore des surprises).

Décrié par une grande partie de la communauté Linux, SystemD s'est pourtant fait une place... il faut donc composer avec lui!

Voici quelques solutions constructives.

Déclaration d'un service SystemD

Nous avons un script Python lcdordertrack.py qui lit des données sur un WebService et afficher les données sur un afficheur LCD USB.

Voici, en quelques étapes, les opérations effectuées pour démarrer automatiquement le script lcdordertrack.py au démarrage du Pi sous SystemD

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 fixer 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 de configuration ("ini"), vous devrez spécifier le chemin complet vers le fichier (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 pouvons voir qu'il y avait un problème dans le script config.py (et donc la lecture de notre config.ini)

C'est la raison pour laquelle nous avons mentionné, plus tôt, qu'il fallait indiqué le chemin d'accès complet vers le fichier de configuration.

Démarrer, arrêter, ...

sudo systemctl start lcdordertrack.service

Voici la commande type qui 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.

Ressources utiles

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

Contourner SystemD (application graphique)

Nous avons également une application PyGame que nous voulions démarrer en même temps que le Raspberry-Pi.

Voici comment nous nous y sommes pris.

  1. Utiliser sudo raspi-config pour logger automatiquement votre pi en mode console
  2. Ecrire un fichier /home/pi/my_app/my_app.sh qui contient de quoi démarrer votre application.
    C'est à la fois pratique durant vos développements et facilite le démarrage
#!/bin/bash

MYAPP_DIR=/home/pi/my_app

cd "${MYAPP_DIR}"

# initialisation diverses pour votre script
if [[ $1 == "set-time" ]]; then
  sudo gnome-control-center datetime
fi

# Utiliser sudo si necessaire
sudo python my_app.py >>my_app.log 2>>my_app.err

cd -
  1. Maintenant modifiez le fichier .baschrc

Rendez vous dans votre répertoire home, puis éditez votre fichier .bashrc

cd ~
nano .bashrc

ajoutez la section similaire à celle ci-dessous pour démarrer automatiquement votre script my_app.sh.

# starts my_app (if not started yet)
ps -a | grep -v grep | grep my_app.sh > /dev/null
result=$?
if [ "${result}" -eq "0" ]
  then echo "MY_APP is already running!"
else
   tty | grep tty1 > /dev/null
   result=$?
   if [ "${result}" -eq "0" ]
   then
       echo "MY_APP starting..."
       sudo /home/pi/my_app/my_app.sh &
   else
       echo "MY_APP not started (autostart reserved to tty1)"
   fi
fi

Ce bout code contient un petit plus!

En effet, il vérifie si le script my_app.sh n'est pas déjà en cours d'exécution avant de le lancer.

Ensuite, le script vérifie que l'on est bien sur le terminal 1 (tty1) avant de lancer le script... cela évite de lancer le script lors d'une connexion ssh (utilisé pour prendre le contrôle à distance).

Toute référence, mention ou extrait de cette traduction doit être explicitement accompagné du texte suivant : «  Traduction par MCHobby (www.MCHobby.be) - Vente de kit et composants » avec un lien vers la source (donc cette page) et ce quelque soit le média utilisé.

L'utilisation commercial de la traduction (texte) et/ou réalisation, même partielle, pourrait être soumis à redevance. Dans tous les cas de figures, vous devez également obtenir l'accord du(des) détenteur initial des droits. Celui de MC Hobby s'arrêtant au travail de traduction proprement dit.