====== Création d'un service UNIX sur le Raspberry pi ======
L'objectif de ce tutoriel est de mettre en place un daemon unix (autrement dit un service) exécutant des tâches programmées par l'utilisateur.
===== Introduction =====
Au vu de la faible consommation minime du Raspberry pi, on pourra souhaiter le charger de diverses tâches sur le réseau, en se connectant à distance via SSH, ou toute autre méthode d'administration. Seulement, si l'utilisateur lance une commande par SSH, et se déconnecte, la commande en cours d'exécution s'interrompra. De plus, si l'on ne connecte pas le Raspberry pi au réseau, comment lancer notre commande? Nous verrons ici une méthode permettant d'automatiser l'exécution d'une commande, et de fournir un service tournant sur le système.
Dès lors que ce service sera lancé, il continuera en effet à s'exécuter, même après la déconnexion de l'utilisateur. Nous verrons également qu'il est possible de lancer ce service automatiquement au démarrage du système.
Imaginons un raspberry pi chargé d'effectuer diverses tâches, à des moments dépendant de l'utilisateur. On pourrait souhaiter qu'au lieu de se connecter pour activer telle ou telle tâche, l'utilisateur puisse se contenter d'appuyer sur un bouton pour lancer tel ou tel programme. C'est un exemple d'application de services.
===== Exemple pratique : affichage sur un écran LCD =====
Dans le cas que nous verrons ici, nous partirons d'un script que j'ai créé pour afficher diverses informations sur un écran LCD connecté au Raspberry pi par les GPIO via un MCP23017 (voir le tutoriel ici : [[raspberry_pi:lcd_via_mcp23017]]).
Je dispose donc d'un script //lcdClock5.py// qui affiche l'IP du Raspberry pi, le ping, la température, la date, l'uptime, l'occupation CPU, etc. L'objectif sera que ce script s'exécute automatiquement sans intervention de ma part. On pourra bien sur utiliser n'importe quel autre script à la place.
===== Création du script dans init.d =====
Pour pouvoir créer un service, il faudra créer, en tant que root, un script dans /etc/inid.d/, du nom souhaité du servie. Dans mon cas, j'ai donc créé le fichier /etc/inid.d/lcd0 :
sudo nano /etc/inid.d/lcd0
Je me suis basé sur ce tutoriel pour écrire le script : http://www.debian-administration.org/articles/28
En pratique, voici le code de mon script :
#! /bin/sh
# /etc/init.d/lcd0
#
# Some things that run always
touch /var/lock/lcd0
script="/home/pi/code/lcdClock5.py"
# Carry out specific functions when asked to by the system
case "$1" in
start)
echo "Starting script lcd0 "
sudo python $script &
;;
stop)
echo "Stopping script lcd0"
sudo kill -9 `ps -eo pid,cmd | grep "python $script" -m 2 | cut -d ' ' -f 1`
;;
*)
echo "Usage: /etc/init.d/blah {start|stop}"
exit 1
;;
esac
exit 0
==== Lancement du service ====
Il y a une section start, qui sera appelée pour lancer le script. Le echo "..." peut être supprimé, mais vous devez dans tous les cas mettre la commande pour lancer le script. Dans mon cas, il s'agit de :
sudo python $script &
sudo permet d'exécuter en root la commande python, qui exécutera le script contenu dans la variable $script. Ma variable $script, définie plus haut, contient le nom de mon script : script="/home/pi/code/lcdClock5.py".
On peut dès lors démarrer le service via la commande suivante :
sudo /etc/init.d/./lcd0 start
==== Arrêt du service ====
Nous aurons également une partie stop, permettant d'arrêter le démon. Dans mon cas, comme il s'agit d'un script python, je ne peux pas me contenter d'un simple "killall nom_du_script", alors j'ai fait quelques recherches. En pratique, le script python exécuté avec sudo lance deux processus, et ma commande permet de récupérer leurs PID. j'utilise alors kill -9 pour tuer les deux processus :
sudo kill -9 `ps -eo pid,cmd | grep "python $script" -m 2 | cut -d ' ' -f 1`
Cela nous permettra d'arrêter le service en invoquant la commande suivante :
sudo /etc/init.d/./lcd0 stop
==== Rendre le script exécutable ====
Avant de pouvoir lancer le service, il faut rendre le script exécutable, via la commande suivante :
sudo chmod 755 /etc/init.d/lcd0
A partir de là, le démon est fonctionnel, et peut être démarré ou arrêté.
==== Permettre le lancement automatique au démarrage du système ====
Si l'on souhaite que le script se lance automatiquement au démarrage, il faudra alors utiliser la commande suivante :
update-rc.d lcd0 defaults
Dans l'état, cela fonctionnera, mais il y aura des warnings. Nous verrons plus tard quoi faire pour faire disparaître les warnings.
==== Désactiver le lancement automatique au démarrage ====
Pour désactiver le lancement automatique, il faudra taper la commande suivante :
update-rc.d -f lcd0 remove
==== Script modifié pour éviter les warnings ====
Afin d'éviter les warnings, nous devons compléter le script, comme suit :
#! /bin/sh
# /etc/init.d/lcd0
#
### BEGIN INIT INFO
# Provides: lcd0
# Required-Start: $local_fs $network
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: lcdscreen daemon
# Description: lcd screen printing realtime data about the system
### END INIT INFO
# Some things that run always
#touch /var/lock/lcd0
script="/home/pi/code/lcdClock5.py"
# Carry out specific functions when asked to by the system
case "$1" in
start)
echo "Starting script lcd0 "
sudo python $script &
;;
stop)
echo "Stopping script lcd0 with pid $PID"
sudo kill -s 9 `ps -eo pid,cmd | grep "python $script" -m 2 | cut -d ' ' -f 1`
;;
*)
echo "Usage: /etc/init.d/blah {start|stop}"
exit 1
;;
esac
exit 0
Pour activer le script au démarrage avec ces modifications, on fera par exemple :
sudo update-rc.d lcd0 start 50 2 3 4 5 . stop 50 0 1 6 .
Voici un [[http://wiki.debian.org/LSBInitScripts|tutoriel détaillant davantage cette partie décrivant le script et les runlevels]].