launchd startInterval más corto que el tiempo que tarda el script en completarse

2

Estoy usando launchctl para cargar / iniciar mi script de Python y funciona hasta cierto punto. Se inicia cada 120 segundos, pero algunas veces mi script tarda 500 segundos en ejecutarse y mi teoría es que si tengo un proceso ejecutándolo, lo reinicia en lugar de dejar que se ejecute el primero.

Lo que creo que sucede: - inicie tester.py (tiempo estimado de tester.py para completar 400 s) - después de 120 s - inicie tester.py nuevamente y abandone el primero

Lo que quiero: para terminar el primer tester.py no reiniciarlo.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>BuildNotification.py</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python</string>
        <string>/Users/xcuer/tester.py</string>
    </array>
    <key>StartInterval</key>
    <integer>120</integer>
    <key>TimeOut</key>
    <integer>7200</integer>
    <key>ExitTimeOut</key>
    <integer>7200</integer>
</dict>
</plist>
donttellunclesam
fuente
Estoy tratando de pensar en una buena solución que no sea hacer que el script compruebe las invocaciones anteriores y salir ...
bmike
@bmike Estoy tratando de ver si crontab resuelve este problema
donttellunclesam
1
Un archivo de bloqueo sería la solución tradicional para esta situación. ¿Eres capaz de modificar el script?
Graham Miln
@GrahamMiln ¿Cómo funcionaría un archivo de bloqueo para mi solución? ¿O hay alguna manera de que pueda escribir un script bash que ejecute llamadas callctl en lugar del script python en sí? ¿Laucnhctl tiene una manera de verificar si un servicio se está ejecutando actualmente?
donttellunclesam
1
Usé la respuesta sugerida de @GrahamMiln para crontaby launchdtrabajos. Su prueba de 4 líneas de shell se puede escribir muy fácilmente en Python, Perl, AppleScript o cualquier lenguaje de script.
dan

Respuestas:

1

launchd se enfoca en lanzar trabajos y mantenerlos en ejecución, no tiene un mecanismo para manejar trabajos superpuestos.

Archivo de bloqueo

Tradicionalmente, en un entorno UNIX, se utiliza un archivo de bloqueo para evitar que los procesos se ejecuten varias veces.

Los pasos centrales son:

  1. Al iniciar el script, si el archivo de bloqueo ya existe, detenga el script.
  2. Al iniciar el script, si el archivo de bloqueo no existe, cree el archivo de bloqueo.
  3. Al finalizar el script, elimine el archivo de bloqueo.

En macOS, cree su archivo de bloqueo /var/tmppara procesos en toda la computadora.

Implementación de muestra

if ! mkdir /var/tmp/myscript.lock 2>/dev/null; then
    echo "Myscript is already running." >&2
    exit 1
fi

Consulte Forma rápida y sucia para garantizar que solo se ejecute una instancia de un script de shell a la vez y ¿Cuál es la mejor manera de garantizar que solo se ejecute una instancia de un script de Bash? para guiones de muestra.

Problemas potenciales

Hay casos extremos.

launchddesea que los trabajos se ejecuten durante al menos n segundos antes de terminar . Cuando el script encuentre un archivo de bloqueo existente, considere dormir durante n segundos y luego salir.

¿Qué sucede si su secuencia de comandos se cierra o sale debido a un error? ¿Puede estar seguro de que se eliminó el archivo de bloqueo?

En C, un truco para garantizar la eliminación de un archivo es crear, abrir y eliminar el archivo; un archivo eliminado que se mantiene abierto en UNIX permanecerá hasta que finalice el proceso de apertura. El archivo se elimina incluso si el proceso falla.

En una secuencia de comandos de shell, capture la señal de finalización y asegúrese de eliminar el archivo.

Otro problema potencial es verificar el archivo existente. Esta comprobación podría ocurrir facciones de segundo antes de que finalice el script anterior. Esto será raro pero posible. El enfoque citado anteriormente pretende superar esto.

Graham Miln
fuente