J'ai un démon python qui s'exécute dans mon application Web/Comment puis-je vérifier rapidement (à l'aide de python) si mon démon est en cours d'exécution et, sinon, le lancer?
Je souhaite le faire de cette manière afin de réparer les plantages du démon. Ainsi, le script ne doit pas nécessairement être exécuté manuellement. Il s'exécutera automatiquement dès qu'il sera appelé, puis continuera à fonctionner.
Comment puis-je vérifier (en utilisant python) si mon script est en cours d'exécution?
Déposez un fichier pid quelque part (par exemple,/tmp). Ensuite, vous pouvez vérifier si le processus est en cours d'exécution en vérifiant si le PID du fichier existe. N'oubliez pas de supprimer le fichier lorsque vous l'arrêtez proprement et vérifiez-le au démarrage.
#/usr/bin/env python
import os
import sys
pid = str(os.getpid())
pidfile = "/tmp/mydaemon.pid"
if os.path.isfile(pidfile):
print "%s already exists, exiting" % pidfile
sys.exit()
file(pidfile, 'w').write(pid)
try:
# Do some actual work here
finally:
os.unlink(pidfile)
Ensuite, vous pouvez vérifier si le processus est en cours d'exécution en vérifiant si le contenu de /tmp/mydaemon.pid est un processus existant. Monit (mentionné ci-dessus) peut le faire pour vous, ou vous pouvez écrire un simple script Shell pour le vérifier pour vous en utilisant le code de retour de ps.
ps up `cat /tmp/mydaemon.pid ` >/dev/null && echo "Running" || echo "Not running"
Pour plus de crédit, vous pouvez utiliser le module atexit pour vous assurer que votre programme nettoie son pidfile en toutes circonstances (mort, exceptions levées, etc.).
Une technique pratique sur un système Linux utilise des sockets de domaine:
import socket
import sys
import time
def get_lock(process_name):
# Without holding a reference to our socket somewhere it gets garbage
# collected when the function exits
get_lock._lock_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
try:
get_lock._lock_socket.bind('\0' + process_name)
print 'I got the lock'
except socket.error:
print 'lock exists'
sys.exit()
get_lock('running_test')
while True:
time.sleep(3)
Il est atomique et évite le problème de fichiers de verrouillage qui traînent si votre processus est envoyé à un SIGKILL
Vous pouvez lisez la documentation de socket.close
que les sockets sont automatiquement fermés lorsque les ordures sont collectées.
La bibliothèque pid peut faire exactement cela.
from pid import PidFile
with PidFile():
do_something()
Il gérera aussi automatiquement le cas où le pidfile existe mais que le processus n'est pas en cours d'exécution.
Bien entendu, l'exemple de Dan ne fonctionnera pas comme il se doit.
En effet, si le script tombe en panne, lève une exception ou ne nettoie pas le fichier pid, le script sera exécuté plusieurs fois.
Je suggère ce qui suit à partir d'un autre site:
Ceci est pour vérifier s'il existe déjà un fichier de verrouillage
\#/usr/bin/env python
import os
import sys
if os.access(os.path.expanduser("~/.lockfile.vestibular.lock"), os.F_OK):
#if the lockfile is already there then check the PID number
#in the lock file
pidfile = open(os.path.expanduser("~/.lockfile.vestibular.lock"), "r")
pidfile.seek(0)
old_pid = pidfile.readline()
# Now we check the PID from lock file matches to the current
# process PID
if os.path.exists("/proc/%s" % old_pid):
print "You already have an instance of the program running"
print "It is running as process %s," % old_pid
sys.exit(1)
else:
print "File is there but the program is not running"
print "Removing lock file for the: %s as it can be there because of the program last time it was run" % old_pid
os.remove(os.path.expanduser("~/.lockfile.vestibular.lock"))
Cela fait partie du code où nous mettons un fichier PID dans le fichier de verrouillage
pidfile = open(os.path.expanduser("~/.lockfile.vestibular.lock"), "w")
pidfile.write("%s" % os.getpid())
pidfile.close()
Ce code vérifiera la valeur de pid par rapport au processus en cours, évitant une double exécution.
J'espère que cela aidera.
Il existe de très bons packages pour le redémarrage de processus sous UNIX. Celui qui a un bon tutoriel sur la construction et la configuration est monit . Avec quelques ajustements, vous pouvez avoir une technologie éprouvée et solide pour garder votre démon.
Il existe une myriade d'options. Une méthode utilise des appels système ou des bibliothèques python qui effectuent de tels appels pour vous. La seconde consiste simplement à générer un processus tel que:
ps ax | grep processName
et analyser la sortie. Beaucoup de gens choisissent cette approche, ce n'est pas nécessairement une mauvaise approche à mon avis.
Essayez cette autre version
def checkPidRunning(pid):
'''Check For the existence of a unix pid.
'''
try:
os.kill(pid, 0)
except OSError:
return False
else:
return True
# Entry point
if __== '__main__':
pid = str(os.getpid())
pidfile = os.path.join("/", "tmp", __program__+".pid")
if os.path.isfile(pidfile) and checkPidRunning(int(file(pidfile,'r').readlines()[0])):
print "%s already exists, exiting" % pidfile
sys.exit()
else:
file(pidfile, 'w').write(pid)
# Do some actual work here
main()
os.unlink(pidfile)
Ma solution consiste à vérifier le processus et les arguments de ligne de commande. Testé sous Windows et Ubuntu Linux.
import psutil
import os
def is_running(script):
for q in psutil.process_iter():
if q.name().startswith('python'):
if len(q.cmdline())>1 and script in q.cmdline()[1] and q.pid !=os.getpid():
print("'{}' Process is already running".format(script))
return True
return False
if not is_running("test.py"):
n = input("What is Your Name? ")
print ("Hello " + n)
Je suis un grand fan de Superviseur pour la gestion des démons. Il est écrit en Python. Il existe donc de nombreux exemples sur la manière d’interagir avec lui ou de l’extraire de Python. Pour vos besoins, API de contrôle de processus XML-RPC devrait bien fonctionner.
Plutôt que de développer votre propre solution de fichier PID (qui comporte plus de subtilités et d’énigmes que vous ne le pensez), jetez un œil à supervisord - c’est un système de contrôle de processus qui facilite le contrôle du travail. et comportements de démon autour d'un script Python existant.
Je suis tombé sur cette vieille question en cherchant moi-même une solution.
Utilisez psutil :
import psutil
import sys
from subprocess import Popen
for process in psutil.process_iter():
if process.cmdline() == ['python', 'your_script.py']:
sys.exit('Process found: exiting.')
print('Process not found: starting it.')
Popen(['python', 'your_script.py'])
n exemple simple si vous recherchez uniquement un nom de processus existe ou non:
import os
def pname_exists(inp):
os.system('ps -ef > /tmp/psef')
lines=open('/tmp/psef', 'r').read().split('\n')
res=[i for i in lines if inp in i]
return True if res else False
Result:
In [21]: pname_exists('syslog')
Out[21]: True
In [22]: pname_exists('syslog_')
Out[22]: False
Voici un code plus utile (avec vérifier si exactement python exécute le script):
#! /usr/bin/env python
import os
from sys import exit
def checkPidRunning(pid):
global script_name
if pid<1:
print "Incorrect pid number!"
exit()
try:
os.kill(pid, 0)
except OSError:
print "Abnormal termination of previous process."
return False
else:
ps_command = "ps -o command= %s | grep -Eq 'python .*/%s'" % (pid,script_name)
process_exist = os.system(ps_command)
if process_exist == 0:
return True
else:
print "Process with pid %s is not a Python process. Continue..." % pid
return False
if __== '__main__':
script_name = os.path.basename(__file__)
pid = str(os.getpid())
pidfile = os.path.join("/", "tmp/", script_name+".pid")
if os.path.isfile(pidfile):
print "Warning! Pid file %s existing. Checking for process..." % pidfile
r_pid = int(file(pidfile,'r').readlines()[0])
if checkPidRunning(r_pid):
print "Python process with pid = %s is already running. Exit!" % r_pid
exit()
else:
file(pidfile, 'w').write(pid)
else:
file(pidfile, 'w').write(pid)
# main programm
....
....
os.unlink(pidfile)
Voici la chaîne:
ps_command = "ps -o command= %s | grep -Eq 'python .*/%s'" % (pid,script_name)
renvoie 0 si "grep" réussit et que le processus "python" est en cours d'exécution avec le nom de votre script en tant que paramètre.
Les autres réponses sont utiles pour des tâches telles que les tâches cron, mais si vous utilisez un démon, vous devez le surveiller avec quelque chose comme daemontools .
essaye ça:
#/usr/bin/env python
import os, sys, atexit
try:
# Set PID file
def set_pid_file():
pid = str(os.getpid())
f = open('myCode.pid', 'w')
f.write(pid)
f.close()
def goodby():
pid = str('myCode.pid')
os.remove(pid)
atexit.register(goodby)
set_pid_file()
# Place your code here
except KeyboardInterrupt:
sys.exit(0)
ps ax | grep processName
si votre script de débogage dans pycharm quitte toujours
pydevd.py --multiproc --client 127.0.0.1 --port 33882 --file processName