Voici la méthode pour lancer un script python en tant que service sur le Raspberry mais c’est valable aussi sur Debian.
EDIT : cette astuce n’est valable que sur les versions wheezy de raspbian , elle ne fonctionne plus avec la nouvelle version Jessie
1 -rendre votre script executable
Pour commencer , assurez vous que votre script soit bien exécutable :
chmod +x monscript.py
testez l’execution de votre script :
./monscript.py
n’utilisez pas la méthode « python monscript.py » car pour la suite du tuto votre script doit être exécutable directement
si votre script ne fonctionne pas , vous avez certainement un problème avec votre shebang ( vous savez la première ligne d’un script )
Normalement sur le Raspberry c’est celle ci :
#!/usr/bin/python
2 – créer un lien vers votre script :
un service doit être lancé depuis /usr/bin ou /usr/sbin ,
nous allons donc créer un lien dans un de ces répertoires pointant vers notre script
sudo ln -s /chemin_de_mon_script/monscript.py /usr/sbin/monscript
notez bien qu’on a enlever l’extension .py
3 – paramétrage du service :
c’est assez simple , il y a un modèle déjà fourni : le fichier skeleton
cd /etc/init.d
sudo cp skeleton monscript
chmod +x monscript
éditez le fichier monscript avec votre éditeur préféré et repérez les lignes suivantes:
PATH=/usr/sbin:/usr/bin:/sbin:/bin DESC= »Description of the service » NAME=daemonexecutablename DAEMON=/usr/sbin/$NAME DAEMON_ARGS= »–options args » PIDFILE=/var/run/$NAME.pid SCRIPTNAME=/etc/init.d/$NAMEne touchez pas aux lignes en rouge et remplacez les lignes vertes par vos valeurs
DESC : ce que vous voulez NAME=monscript DAEMON_ARGS= » »(si votre script n’a pas besoin de paramètre)
ensuite repérez les lignes suivantes:
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon –start –quiet –pidfile $PIDFILE –exec $DAEMON –test > /dev/null \
|| return 1
start-stop-daemon –start –quiet –pidfile $PIDFILE –exec $DAEMON — \
$DAEMON_ARGS \
|| return 2
Pour pouvoir arrêter un service, il faut connaître son PID (identifiant du processus). Soit c’est votre programme qui crée le fichier .pid , soit c’est le service. En général c’est plus simple de laisser le service s’occuper de ce pid, il faut dans ce cas ajoutez l’option –make-pidfile (voir ci-dessous).
si votre script ne rends pas la main ( il boucle en permanence ) alors il faut le lancer en mode background. Il faut dans ce cas ajouter l’option –background
voici les lignes finales:
start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2
4 – voila le service est prêt il faut maintenant le tester :
sudo service monscript start
sudo service monscript status
sudo service monscript stop
si tout va bien nous passons a la suite : le lancement automatique au boot :
sudo update-rc.d monscript defaults 99
update-rc.d se charge de créer tout ce qu’il faut pour lancer un service , le chiffre 99 corresponds a l’ordre de lancement au boot , ici en dernier après tous les autres
Merci pour ce tuto, très synthétique. Efficace, exactement ce que je recherchais !
J’aimeJ’aime
Merci aussi : cela m’a permis de mettre en place mon premier service Python en quelques minutes ! J’ai perdu un peu de temps avec un truc tout bête : à la fin de l’étape 3, il ne faut pas oublier de rendre le fichier de paramétrage du service executable lui aussi (un chmod +x monscript). Sans cela, le service n’est pas trouvé…
J’aimeJ’aime
J’étais à 2 doigts de m’auto flageller pour cet oubli avant de me rendre compte que je précise bien cette manip au tout début de mon article ouf 🙂
J’aimeJ’aime
Oui, et je l’avais bien fait pour monscript.py….mais je parle du fichier de paramètrage (le clone du skeleton) qui doit aussi subir ce sort. Comme tu ne l’avais pas dit, je ne l’avais pas fait…et j’ai bien dû perdre 15 min à chercher d’où le problème venait. Encore merci en tout cas.
J’aimeJ’aime
Ah merde 15 minutes quand même…
J’aimeJ’aime
bonjour,
je suis sur Raspberry Pi 3 avec Jessie
j’ai suivi ce tuto , mais j’ai un problème:
le service démarre bien mais le programme n’est pas actif…
resultat du journalctl -xn
/* **************** */
root@raspberrypi:/etc/init.d# journalctl -xn
— Logs begin at ven. 2016-10-28 14:03:16 CEST, end at ven. 2016-10-28 16:42:08 CEST. —
oct. 28 16:41:51 raspberrypi systemd[1]: Started LSB: Example initscript.
— Subject: L’unité (unit) rdm880.service a terminé son démarrage
— Defined-By: systemd
— Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
—
— L’unité (unit) rdm880.service a terminé son démarrage, avec le résultat done.
oct. 28 16:41:51 raspberrypi sudo[1330]: pam_unix(sudo:session): session closed for user root
oct. 28 16:41:53 raspberrypi sudo[1362]: pi : TTY=pts/0 ; PWD=/home/pi ; USER=root ; COMMAND=/usr/sbin/service rdm880 status
oct. 28 16:41:53 raspberrypi sudo[1362]: pam_unix(sudo:session): session opened for user root by pi(uid=0)
oct. 28 16:41:53 raspberrypi sudo[1362]: pam_unix(sudo:session): session closed for user root
oct. 28 16:42:08 raspberrypi sudo[1372]: pi : TTY=pts/0 ; PWD=/home/pi ; USER=root ; COMMAND=/bin/su
oct. 28 16:42:08 raspberrypi sudo[1372]: pam_unix(sudo:session): session opened for user root by pi(uid=0)
oct. 28 16:42:08 raspberrypi su[1376]: Successful su for root by root
oct. 28 16:42:08 raspberrypi su[1376]: + /dev/pts/0 root:root
oct. 28 16:42:08 raspberrypi su[1376]: pam_unix(su:session): session opened for user root by pi(uid=0)
/* ************* */
mon script a base de skeleton :
/* *************** */
#!/bin/sh
# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and sourcing.
if [ true != « $INIT_D_SCRIPT_SOURCED » ] ; then
set « $0 » « $@ »; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
fi
### BEGIN INIT INFO
# Provides: skeleton
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Example initscript
# Description: This file should be used to construct scripts to be
# placed in /etc/init.d. This example start a
# single forking daemon capable of writing a pid
# file. To get other behavoirs, implemend
# do_start(), do_stop() or other functions to
# override the defaults in /lib/init/init-d-script.
### END INIT INFO
# Author: Foo Bar
#
# Please remove the « Author » lines above and replace them
# with your own name if you copy and modify this script.
PATH=/usr/sbin:/usr/bin:/sbin:/bin
DESC= »RFID rdm880 service »
NAME=rdm880
DAEMON=/usr/sbin/$NAME
DAEMON_ARGS= » »
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon –start –quiet –background –make-pidfile –pidfile $PIDFILE –exec $DAEMON –test > /dev/null \
|| return 1
start-stop-daemon –start –quiet –background –make-pidfile –pidfile $PIDFILE –exec $DAEMON — \ $DAEMON_ARGS \
|| return 2
}
/* ************** */
Mon script python
/* ********************* */
#!/usr/bin/python
# -*-coding:Utf-8 -*
import serial
import time
import wiringpi
import MySQLdb
import RPi.GPIO as GPIO
from datetime import datetime
from binascii import hexlify
serial=serial.Serial(« /dev/ttyAMA0″,
baudrate=9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=0.1)
wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(18, 1)
db = MySQLdb.connect(host= »192.168.1.90″, user= »user », passwd= »QY7R97H », db= »porte »)
cur = db.cursor()
query = (« SELECT * FROM droit_acces WHERE Code = %s LIMIT 1 »)
ID_rong = 128187 # reader respone if no card
chuoi= « \xAA\x00\x03\x25\x26\x00\x00\xBB »
def RFID(str): #function read RFID via uart
serial.write(chuoi)
data = serial.readline()
tach_5 = data[5]
tach_6 = data[6]
hex_5 = hexlify(tach_5)
hex_6= hexlify(tach_6)
num_5 = int(hex_5,16)
num_6 = int(hex_6,16)
num_a = num_5 * 1000 + num_6
if(num_a != ID_rong):
tach_7 = data[7]
tach_8 = data[7]
hex_7 = hexlify(tach_7)
hex_8= hexlify(tach_8)
num_7 = int(hex_7,16)
num_8 = int(hex_8,16)
num = num_8 + num_7 * 1000 + num_6 * 1000000 + num_5 * 1000000000
else:
num = num_5 * 1000 + num_6
return num
while 1:
num = RFID(chuoi)
if num != ID_rong:
# print « no card …. »
# else:
# print « Card Serial:%d » % num
cur.execute(query, « %d » % num )
row = cur.fetchone()
if row is not None:
# print « %s » % row[2]
# print « %s » % row[0]
wiringpi.digitalWrite(18, 1)
time.sleep(2)
wiringpi.digitalWrite(18, 0)
# else:
# print « BAD card …. »
time.sleep(1)
/* ********************* */
doit-on le voir avec la commande ps -ef | grep monscript ??
qu’ai-je oublié ?
d’avance merci de voter aide …
J’aimeJ’aime
Je suis désolé mais ma méthode ne fonctionne qu’avec la version wheezy
J’aimeJ’aime
Bonjour,
quelqu’un a-t-il la solution pour démarrer un programme python au démarrage de jessie?
J’écume le web depuis une semaine, j’essaie plein de trucs, mais au final, rien ne fonctionne.
Donc si une âme charitable pouvait nous faire profiter de sa solution éprouvée…
J’aimeJ’aime
j’ai trouvé ça mais je n’ai pas testé :
http://www.diegoacuna.me/how-to-run-a-script-as-a-service-in-raspberry-pi-raspbian-jessie/
J’aimeJ’aime
j’ai solutionné le problème en mettant une ligne de commande dans rc.local…
je creer un programme python exemple rdm880.py
je le rends executable
je créé un lien dans /usr/sbin/
et dans le rc.local j’ajoute la ligne suivante :
sudo /usr/sbin/rdm880 &
J’aimeJ’aime
@jahislove, merci pour cette réponse.
C’est cette solution qui fonctionne le mieux pour moi, sauf que je suis obligé de rajouter dans le crontab la ligne @reboot sudo systemctl restart MonService.service pour qu’il redémarre vraiment.
Dès que j’ai que j’ai du temps (il faut bien que je passe à autre chose), je reprendrai tout à zéro, y compris la solution de @Delamarre jean-paul, car j’ai fait tellement d’essais que je ne sais plus très bien ce que j’ai réellement fait.
Ça me permettra de nettoyer un peu par la même occasion.
Merci à vous deux.
J’aimeJ’aime