Compruebe si el script de Python se está ejecutando

Tengo un daemon de Python ejecutándose como parte de mi aplicación web / ¿Cómo puedo verificar rápidamente (usando python) si mi daemon se está ejecutando y, si no, lanzarlo?

Quiero hacerlo de esa manera para solucionar cualquier locking del daemon, por lo que el script no tiene que ejecutarse manualmente, se ejecutará automáticamente tan pronto como se llame y luego seguirá funcionando.

¿Cómo puedo verificar (usando python) si mi script está en ejecución?

Coloque un archivo pid en algún lugar (por ejemplo, / tmp). Luego puede verificar si el proceso se está ejecutando al verificar si existe el PID en el archivo. No olvide eliminar el archivo cuando lo cierre de forma limpia, y verifique que se inicie.

#/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) 

Luego, puede verificar si el proceso se está ejecutando al verificar si el contenido de /tmp/mydaemon.pid es un proceso existente. Monit (mencionado anteriormente) puede hacer esto por usted, o puede escribir un script de shell simple para verificarlo usando el código de retorno de ps.

 ps up `cat /tmp/mydaemon.pid ` >/dev/null && echo "Running" || echo "Not running" 

Para obtener crédito adicional, puede usar el módulo atexit para asegurarse de que su progtwig limpie su archivo pid bajo cualquier circunstancia (cuando se eliminen, se generen excepciones, etc.).

Una técnica que es útil en un sistema Linux es usar sockets de dominio:

 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) 

Es atómico y evita el problema de tener archivos de locking por ahí si su proceso recibe un SIGKILL

Puede leer en la documentación de socket.close que los sockets se cierran automáticamente cuando se recolecta la basura.

La librería pid puede hacer exactamente esto.

 from pid import PidFile with PidFile(): do_something() 

También manejará automáticamente el caso en el que existe el archivo pid, pero el proceso no se está ejecutando.

Hay paquetes muy buenos para reiniciar procesos en UNIX. Uno que tiene un gran tutorial sobre cómo construirlo y configurarlo es monit . Con algunos ajustes, puedes tener una tecnología probada y sólida como una roca para mantener tu demonio.

Por supuesto, el ejemplo de Dan no funcionará como debería ser.

De hecho, si el script falla, se genera una excepción o no limpia el archivo pid, el script se ejecutará varias veces.

Sugiero lo siguiente basado en otro sitio web:

Esto es para comprobar si ya existe un archivo de locking

 \#/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")) 

Esto es parte del código donde colocamos un archivo PID en el archivo de locking.

 pidfile = open(os.path.expanduser("~/.lockfile.vestibular.lock"), "w") pidfile.write("%s" % os.getpid()) pidfile.close() 

Este código verificará el valor de pid en comparación con el proceso en ejecución existente, evitando la ejecución doble.

Espero que te ayude.

Hay una gran variedad de opciones. Un método es usar llamadas al sistema o bibliotecas de Python que realizan dichas llamadas por usted. El otro es simplemente generar un proceso como:

 ps ax | grep processName 

y analizar la salida. Muchas personas eligen este enfoque, no es necesariamente un mal enfoque desde mi punto de vista.

Prueba esta otra versión

 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 __name__ == '__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) 

Soy un gran fan de Supervisor para la gestión de demonios. Está escrito en Python, por lo que hay muchos ejemplos de cómo interactuar con Python o extenderlo. Para sus propósitos, la API de control de procesos XML-RPC debería funcionar bien.

Mi solución es verificar el proceso y los argumentos de la línea de comandos Probados en Windows y 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) 

Encontré esta vieja pregunta en busca de una solución.

Utilice 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']) 

Las otras respuestas son excelentes para tareas como las tareas de cron, pero si está ejecutando un demonio, debe monitorearlo con algo como daemontools .

 ps ax | grep processName 

Si yor debug script en pycharm siempre sale

 pydevd.py --multiproc --client 127.0.0.1 --port 33882 --file processName 

En lugar de desarrollar su propia solución de archivo PID (que tiene más sutilezas y casos de esquina de lo que podría pensar), eche un vistazo a Supervord : este es un sistema de control de procesos que facilita el control de los trabajos y los comportamientos de los demonios en torno a un Python existente. guión.

prueba esto:

 #/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) 

Aquí hay un código más útil (con la comprobación de si Python ejecuta el script exactamente):

 #! /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 __name__ == '__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) 

Aquí está la cadena:

 ps_command = "ps -o command= %s | grep -Eq 'python .*/%s'" % (pid,script_name) 

devuelve 0 si "grep" tiene éxito, y el proceso "python" se está ejecutando actualmente con el nombre de su script como parámetro.

Un ejemplo simple si solo busca un nombre de proceso existe o no:

 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 

Considera el siguiente ejemplo para resolver tu problema:

 #!/usr/bin/python # -*- coding: latin-1 -*- import os, sys, time, signal def termination_handler (signum,frame): global running global pidfile print 'You have requested to terminate the application...' sys.stdout.flush() running = 0 os.unlink(pidfile) running = 1 signal.signal(signal.SIGINT,termination_handler) pid = str(os.getpid()) pidfile = '/tmp/'+os.path.basename(__file__).split('.')[0]+'.pid' if os.path.isfile(pidfile): print "%s already exists, exiting" % pidfile sys.exit() else: file(pidfile, 'w').write(pid) # Do some actual work here while running: time.sleep(10) 

Sugiero este script porque puede ejecutarse una sola vez.

Usando bash para buscar un proceso con el nombre del script actual. No hay archivo extra.

 import commands import os import time import sys def stop_if_already_running(): script_name = os.path.basename(__file__) l = commands.getstatusoutput("ps aux | grep -e '%s' | grep -v grep | awk '{print $2}'| awk '{print $2}'" % script_name) if l[1]: sys.exit(0); 

Para probar, añadir

 stop_if_already_running() print "running normally" while True: time.sleep(3) 

Esto es lo que uso en Linux para evitar iniciar un script si ya se está ejecutando:

 import os import sys script_name = os.path.basename(__file__) pidfile = os.path.join("/tmp", os.path.splitext(script_name)[0]) + ".pid" def create_pidfile(): if os.path.exists(pidfile): with open(pidfile, "r") as _file: last_pid = int(_file.read()) # Checking if process is still running last_process_cmdline = "/proc/%d/cmdline" % last_pid if os.path.exists(last_process_cmdline): with open(last_process_cmdline, "r") as _file: cmdline = _file.read() if script_name in cmdline: raise Exception("Script already running...") with open(pidfile, "w") as _file: pid = str(os.getpid()) _file.write(pid) def main(): """Your application logic goes here""" if __name__ == "__main__": create_pidfile() main() 

Este enfoque funciona bien sin ninguna dependencia de un módulo externo.