Daemonizing un script python dans debian
J'ai un script python que je veux exécuter en arrière-plan au démarrage. C'est le script:
#!/usr/bin/python
from Adafruit_CharLCD import Adafruit_CharLCD
from subprocess import *
from time import sleep, strftime
from datetime import datetime
from datetime import timedelta
from os import system
from os import getloadavg
from glob import glob
#Variables
lcd = Adafruit_CharLCD() #Stores LCD object
cmdIP = "ip addr show eth0 | grep inet | awk '{print $2}' | cut -d/-f1" #Current IP
cmdHD = "df -h /| awk '{print $5}'" # Available hd space
cmdSD = "df -h /dev/sda1 | awk '{print $5}'" # Available sd space
cmdRam = "free -h"
temp = 0
#Run shell command
def run_cmd(cmd):
p = Popen(cmd, shell=True, stdout=PIPE)
output = p.communicate()[0]
return output
#Initalises temp device
def initialise_temp():
#Initialise
system("sudo modprobe w1-gpio")
system("sudo modprobe w1-therm")
#Find device
devicedir = glob("/sys/bus/w1/devices/28-*")
device = devicedir[0]+"/w1_slave"
return device
#Gets temp
def get_temp(device):
f = open (device, 'r')
sensor = f.readlines()
f.close()
#parse results from the file
crc=sensor[0].split()[-1]
temp=float(sensor[1].split()[-1].strip('t='))
temp_C=(temp/1000.000)
temp_F = ( temp_C * 9.0 / 5.0 ) + 32
#output
return temp_C
#Gets time
def get_time():
return datetime.now().strftime('%b %d %H:%M:%S\n')
#Gets uptime
def get_uptime():
with open('/proc/uptime', 'r') as f:
seconds = float(f.readline().split()[0])
array = str(timedelta(seconds = seconds)).split('.')
string = array[0].split(' ')
totalString = string[0] + ":" + string[2]
return totalString
#Gets average load
def get_load():
array = getloadavg()
average = 0
for i in array:
average += i
average = average / 3
average = average * 100
average = "%.2f" % average
return str(average + "%")
#def get_ram():
def get_ram():
ram = run_cmd(cmdRam)
strippedRam = ram.replace("\n"," ");
splitRam = strippedRam.split(' ')
totalRam = int(splitRam[52].rstrip("M"))
usedRam = int(splitRam[59].rstrip("M"))
percentage = "%.2f" % ((float(usedRam) / float(totalRam)) * 100)
return percentage + "%"
#Gets the SD usage
def get_sd():
sd = run_cmd(cmdSD)
strippedSD = sd.lstrip("Use%\n")
return strippedSD
#Gets the HD usage
def get_hd():
hd = run_cmd(cmdSD)
strippedHD = hd.lstrip("Use%\n")
return strippedHD
def scroll():
while(1):
lcd.scrollDisplayLeft()
sleep(0.5)
#Uptime and IP
def screen1():
uptime = get_uptime()
lcd.message('Uptime %s\n' % (uptime))
ipaddr = run_cmd(cmdIP)
lcd.message('IP %s' % (ipaddr))
#Ram and load
def screen2():
ram = get_ram()
lcd.message('Ram Used %s\n' % (ram))
load = get_load()
lcd.message('Avg Load %s' % (load))
#Temp and time
def screen3():
time = get_time();
lcd.message('%s\n' % (time))
lcd.message('Temp %s' % (temp))
#HD and SD usage
def screen4():
sd = get_sd()
lcd.message('SD Used %s\n' % (sd))
hd = get_hd()
lcd.message('HD Used %s' % (hd))
#Pause and clear
def screenPause(time):
sleep(time)
#In here to reduce lag
global temp
temp = str(get_temp(device));
lcd.clear()
###########################################################################################################
#Initialise
lcd.begin(16,2)
device = initialise_temp()
lcd.clear()
#Testing
#Main loop
while(1):
screen1()
screenPause(5)
screen2()
screenPause(5)
screen3()
screenPause(5)
screen4()
screenPause(5)
Je sais que j'ai probablement havnt fait les choses à la façon d'écrire, mais sa première tentative.
Mon script de démarrage dans /etc/init.d C'est le script:
#! /bin/sh
### BEGIN INIT INFO
# Provides: LCD looping
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: LCD daemon
# Description: This file should be used to construct scripts to be
# placed in /etc/init.d.
### END INIT INFO
# Author: Foo Bar <[email protected]>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Loops the LCD screen through LCD.py"
NAME=startup.py
DAEMON=/home/pi/Programming/LCD/startup.py
DAEMON_ARGS=""
PIDFILE=/var/run/daemonLCD.pid
SCRIPTNAME=/etc/init.d/daemonLCD
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/daemonLCD ] && . /etc/default/daemonLCD
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
#
# 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
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one. As a last resort, sleep for some time.
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
#
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
return 0
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out
# and leave 'force-reload' as an alias for 'restart'.
#
#log_daemon_msg "Reloading $DESC" "$NAME"
#do_reload
#log_end_msg $?
#;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
:
Im pense que j'ai raté quelque chose car quand je tape daemonLCD début il dit commande introuvable.
Toute entrée serait génial.
Grâce
êtes-vous sûr que c'est ce qu'il dit. il est plus probable
pi@raspberrypi /etc/init.d $ daemonLCD start-bash: daemonLCD: command not found
Possible duplicata de celui-ci : stackoverflow.com/questions/13718821/...
<FOO> :command not found
ou quelque chose comme ça... qu'est-ce foo?pi@raspberrypi /etc/init.d $ daemonLCD start-bash: daemonLCD: command not found
hostname -i
serait une solution plus facile pour obtenir votre ip actuellePossible duplicata de celui-ci : stackoverflow.com/questions/13718821/...
OriginalL'auteur Joseph Roberts | 2012-12-19
Vous devez vous connecter pour publier un commentaire.
En supposant que vous pouvez gérer plus d'un démon dans l'avenir, laissez-moi vous recommander Supervisord. C'est beaucoup plus simple que l'écriture et la gestion de votre propre init.d scripts.
Par exemple, à partir de votre script serait aussi facile que de les intégrer dans la conf:
- Je utiliser une init.d script disponible ici. Renommer supervisord et le copier dans votre /etc/init.d/puis exécutez:
Je crois que le script d'initialisation a supervisord exécuter en tant que root en tant que par défaut. Vous pouvez le faire tomber à exécuter en tant qu'un autre utilisateur si vous le souhaitez. Je ne suis pas si les enfants s'exécuter en tant que root ou pas, bien que je suppose pas. Aller de l'avant et de vérifier, mais si ils ne le font pas, vous pouvez coller un sudo avant la commande python dans votre supervisord.conf où vous appelez le script.
Ce qui ne fonctionne pas, (ou si vous voulez supervisord à exécuter en tant que root, mais veulent toujours votre script de s'exécuter en tant que root), vous pouvez permettre à personne (ou un groupe d'utilisateurs) pour exécuter le script python en tant que root (bien que vous devriez faire tout à fait certain que ce script ne peut pas être modifié par une personne autre que root).
modifier votre fichier sudoers avec "sudo visudo" et ajouter la ligne suivante à la fin:
Alors assurez-vous d'avoir un beau spectacle au début de votre script python et modifier la commande d'omettre le python appel, je l'ai.e:
Aussi, ne vous définissez supervisord à exécuter au démarrage en utilisant update-rc.d? Si oui, dois-je déplacer mon supervisord les fichiers de/usr / local/bin /etc/init.d? Merci encore
Permettez-moi de savoir si la mise à jour de config/ root œuvres de trucs.
Je l'ai eu à travailler. Grâce sarwar
OriginalL'auteur sarwar
Voici un bon blog qui traite de cette question: L'obtention d'un script Python pour exécuter en arrière-plan (comme un service) sur boot
OriginalL'auteur Daniel F
Utilisation
daemontools
de djb. Il est beaucoup plus facile que les autres réponses fournies. Pour commencer, vous pouvez installer daemon tools avec apt-get de sorte que vous n'avez pas besoin de s'inquiéter à propos de l'accaparement d'une écriture inconnue à partir d'un gist et vous obtenez des mises à jour de debian comme d'habitude. daemontools prend également soin de redémarrer le service, si il meurt, et fournit pour la journalisation. Il y a une description de daemontools et debian ici:http://blog.rtwilson.com/how-to-set-up-a-simple-service-to-run-in-the-background-on-a-linux-machine-using-daemontools/
djb de la page d'aout
daemontools
:http://cr.yp.to/daemontools.html
OriginalL'auteur dfc
C'est une erreur classique d'Unix/Linux, les utilisateurs font.
/etc/init.d
n'est pas dans votre chemin d'accès qui est pourquoi vous ne pouvez pas exécuter daemonLCD. Essayez d'utiliser le chemin d'accès complet (/etc/init.d/daemonLCD start
) ou en ajoutant ./(./daemonLCD start
).Le script doit être exécutable, soit de la ci-dessus pour travailler.
OriginalL'auteur Martin
merci pour le code ci-dessus. Je l'ai utilisé pour comprendre comment mettre en place un démon sur une machine linux.
Avec quelques réglages que j'ai pu obtenir que cela fonctionne assez bien.
Mais quelque chose me laisse perplexe. Et qui a été de vérifier si le processus était en cours d'exécution, la vérification de la existe de /var/run/monfichier.pid
C'est juste le pidfile - et non PAS le processus, droit?
Prendre un coup d'oeil dans /lib/lsb/init-functions.status_of_proc
Qui ne traite que de la réussite ou de l'échec de l'accès au fichier PID.
Maintenant, je suis en train de construire ce démon d'aller sur un petit appareil. J'ai découvert, c'est à l'aide de BusyBox et je n'ai pas de init-functions 🙁
Mais j'ai pidof.
J'ai donc ajouté
et vérifié $LOGFILE et voilà les chiffres sont différents.
Je n'ai pstree -s -p sur les deux numéros et
la pidof nombre crache une très courte de l'arbre, il est donc pour le niveau de la racine du processus de
mais le $PIDFILE nombre vomit hors branche après branche, donc je ne pense pas pstree pouvez trouver le processus.
Oui, le do_stop Joseph Baldwin Roberts code de tuer tous les deux processus. Mais si le processus est tué d'une autre manière, par exemple kill -9 12345, l' $PIDFILE est toujours là. Donc, le démon va croire faussement que le processus est déjà en cours d'exécution un refuser de démarrer.
OriginalL'auteur mycowan