Comprobando la ejecución del script python dentro del script python

Estoy ejecutando un script de python que puede o no tardar unas horas en completarse.

Al comienzo de mi script de python, quiero comprobar si este script de python ya se está ejecutando o no.

Si ya se está ejecutando, quiero salir de mi python actual que acabo de comenzar.

Por ejemplo:

python inició 1AM y continúa ejecutándose hasta que 3AM inició otro a las 2AM sin saber que ya se está ejecutando. Quiero que mi Python 2AM verifique y salga ya que ya se está ejecutando.

¿Cómo puedo escribir este python?


Esto es lo que he intentado bloquear.

try: l = lock.lock("/home/auto.py", timeout=600) # wait at most 10 minutes except error.LockHeld: e = sys.exc_info()[0] logging.error("Error: " + str(e) + " at main gatering Stats") smtpObj.sendmail(sender, receivers, message + "Error: " + str(e) + " at main gatering stats") exit("Fail: " + str(e) + " at main gathering Stats") else: l.release() 

así que pensé que esto esperará 10 minutos si aún se está ejecutando y luego salir … si ya no se está ejecutando, ejecute el python actual

Puede intentar usar el comando lockfile-create con el indicador r para reintentar una cantidad específica de veces al capturar un CalledProcessError y salir, el indicador -p almacenará el pid del proceso:

 import os import sys from time import sleep from subprocess import check_call, CalledProcessError try: check_call(["lockfile-create", "-q","-p", "-r", "0", "-l", "my.lock"]) except CalledProcessError as e: print("{} is already running".format(sys.argv[0])) print(e.returncode) exit(1) # main body for i in range(10): sleep(2) print(1) check_call(["rm","-f","my.lock"]) 

Ejecutar una test.py comandos test.py con el código anterior mientras que uno ya está ejecutando produce lo siguiente:

 $ python lock.py lock.py is already running 4 

Opciones

-q, –quiet

Suprimir cualquier salida. El éxito o el fracaso solo se indicarán mediante el estado de salida.

-v, –verbose

Habilitar salida de diagnóstico.

-l, – nombre de locking

No agregue .lock al nombre de archivo. Esta opción se aplica a lockfile-create, lockfile-remove, lockfile-touch o lockfile-check.

-p, –use-pid

Escriba el id del proceso actual (PID) en el archivo de locking cada vez que se cree un archivo de locking, y use ese pid para verificar la validez de un locking. Consulte la página de manual de lockfile_create (3) para obtener más información. Esta opción se aplica a lockfile-create, lockfile-remove, lockfile-touch y lockfile-check.

-o, –onehot

Toque la cerradura y salga inmediatamente. Esta opción se aplica a lockfile-touch y mail-touchlock. Cuando no se proporcionan, estos comandos se ejecutarán para siempre, tocando el locking una vez por minuto hasta que se eliminen.

-r recuento de rebashs, –retry recuento de rebashs

Trate de bloquear los tiempos de rebash del nombre de archivo antes de rendirse. Cada bash se retrasará un poco más que el último (en incrementos de 5 segundos) hasta alcanzar un retraso máximo de un minuto entre los rebashs. Si el recuento de rebashs no está especificado, el valor predeterminado es 9, que se dará por vencido después de 180 segundos (3 minutos) si fallan los 9 bashs de locking.

Descripción

La función lockfile_create crea un archivo de locking de una manera segura NFS.

Si los indicadores se establecen en L_PID, lockfile_create no solo comprobará un archivo de locking existente, sino que también leerá el contenido para ver si contiene un ID de proceso en ASCII. Si es así, el archivo de locking solo es válido si ese proceso aún existe.

Si el archivo de locking está en un sistema de archivos compartido, puede haber sido creado por un proceso en un host remoto. Por lo tanto, la verificación de la identificación del proceso es inútil y el indicador L_PID no debe establecerse. En este caso, no hay una buena manera de ver si un archivo de locking está obsoleto. Por lo tanto, si el archivo de locking es más antiguo que 5 minutos, se eliminará. Es por eso que se proporciona la función lockfile_touch: mientras se mantiene el locking, debe actualizarse regularmente (cada minuto aproximadamente) llamando a lockfile_touch ().

La función lockfile_check comprueba si un archivo de locking válido ya está presente sin intentar crear un nuevo archivo de locking.

Finalmente, la función lockfile_remove elimina el archivo de locking.

El algoritmo

El algoritmo que se utiliza para crear un archivo de locking de forma atómica, incluso sobre NFS, es el siguiente:

1

Se crea un archivo único. En formato printf, el nombre del archivo es .lk% 05d% x% s. El primer argumento (% 05d) es el id del proceso actual. El segundo argumento (% x) consiste en los 4 bits menores del valor devuelto por el tiempo (2). El último argumento es el nombre de host del sistema.

2

Entonces el archivo de locking se crea utilizando el enlace (2). El valor de retorno del enlace se ignora.

3

Ahora el archivo de locking es stat () ed. Si la estadística falla, vamos al paso 6.

4

El valor estadístico del archivo de locking se compara con el del archivo temporal. Si son iguales, tenemos la cerradura. El archivo temporal se elimina y se devuelve un valor de 0 (éxito) a la persona que llama.

5

Se realiza una comprobación para ver si el archivo de locking existente es válido. Si no es válido, se elimina el archivo de locking obsoleto.

6

Antes de volver a intentarlo, dormimos durante n segundos. n es inicialmente de 5 segundos, pero después de cada rebash, se agregan 5 segundos adicionales hasta un máximo de 60 segundos (un retroceso incremental). Luego vamos al paso 2 hasta rebashs.

Parece que hay un paquete equivalente llamado lockfile-progs en redhat .

En mac puedes usar lockfile y hacer algo como:

 import os import sys from time import sleep import os from subprocess import Popen, CalledProcessError, check_call p = Popen(["lockfile", "-r", "0", "my.lock"]) p.wait() if p.returncode == 0: with open("my.pid", "w") as f: f.write(str(os.getpid())) else: try: with open("my.pid") as f: # see if process is still running or lockfile # is left over from previous run. r = f.read() check_call(["kill", "-0", "{}".format(r)]) except CalledProcessError: # remove old lock file and create new check_call(["rm", "-f", "my.lock"]) check_call(["lockfile", "-r", "0", "my.lock"]) # update pid with open("my.pid", "w") as out: out.write(str(os.getpid())) print("Deleted stale lockfile.") else: print("{} is already running".format(sys.argv[0])) print(p.returncode) exit(1) # main body for i in range(10): sleep(1) print(1) check_call(["rm", "-f", "my.lock"]) 

En su caso, tal vez el uso de un socket funcionaría:

 from socket import socket, gethostname, error, SO_REUSEADDR, SOL_SOCKET from sys import argv import errno sock = socket() # Create a socket object host = gethostname() # /proc/sys/net/ipv4/ip_local_port_range is 32768 61000 on my Ubuntu Machine port = 60001 # allow connection in TIME_WAIT sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) try: sock.bind((host, port)) sock.connect((host, port)) except error as e: # [Errno 99] Cannot assign requested address if e.errno == errno.EADDRNOTAVAIL: print("{} is already running".format(argv[0])) exit(1) # else raise the error else: raise e # main body from time import sleep while True: print(1) sleep(2) sock.close()