0 votos

Ejecutar script Atómicamente

Tengo una tarea launchd que ejecuta un bash script periódicamente, y esto funciona muy bien. Sin embargo, si cambio el script mientras la tarea se está ejecutando, ya sea editándolo directamente, o cambiándolo por una copia actualizada, puede hacer que la tarea en ejecución arroje un montón de errores de sintaxis o, peor aún, tenga un comportamiento impredecible.

El problema parece ser que en lugar de cargar el script en memoria, o mantener abierto el archivo tal y como estaba en el momento de la ejecución, launchd (o probablemente el propio bash) está cargando el archivo en vivo línea a línea, esto significa que cualquier cambio en el script parece reflejarse en tiempo real, provocando errores.

Para tratar de ilustrar el problema, considere lo siguiente:

if [ "$foo" = '1' ]; then
    do_something_that_takes_time
fi

Ahora, imagina que el script se ejecuta en la línea 2 ( do_something_that_takes_time ) y cambio el script, eliminando el if/fi bloque por completo. Cuando el script pasa a la línea 3, ya no encontrará fi y seguirá ejecutando esperando encontrar un fi pero nunca lo hará, resultando en un eventual error (final inesperado del archivo). También puede acabar saltándose comandos (que se adelantaron como resultado de la eliminación de líneas).

Por supuesto que puedo evitar este problema descargando la tarea launchd, actualizándola, y luego volviéndola a cargar, pero esto no es muy conveniente, especialmente para las tareas que pueden tardar mucho tiempo en completarse (ya que preferiría dejarlas terminar, pero no parece haber manera de hacerlo y cambiar el archivo en ese momento). De lo contrario, tengo que añadir algún mecanismo para evitar que la tarea se relance, de modo que pueda intercambiar el nuevo script a mi antojo, pero esto parece un paso extra innecesario cuando Bash debería simplemente ejecutar el script que le indiqué, en el momento en que se inició.

Así que mi pregunta es la siguiente: ¿hay alguna forma de forzar a launchd (o a Bash) a ejecutar el script sólo como estaba cuando comenzó la tarea? Por ejemplo, cargándolo completamente en la memoria antes de ejecutarlo, o cargándolo desde un archivo abierto que no cambie.

Estoy publicando esto aquí porque no estoy del todo seguro de si esto es una rareza de Bash en general, o potencialmente Mac específico de alguna manera. El volumen que estoy ejecutando desde está usando APFS, por lo que debería ser copia-en-escritura, por lo que no esperaría que este comportamiento ocurriera (ya que un manejador de archivo abierto debería continuar apuntando al archivo antiguo, ignorando cualquier cambio que se haga).

1voto

Douglas Puntos 10417

Así que mi pregunta es la siguiente; ¿hay alguna forma de forzar a launchd (o a bash) a ejecutar el script sólo como estaba cuando empezó la tarea?

No. No es una peculiaridad de bash o launchd . launchd carga el trabajo (plist) en la memoria, no el script. El script es llamado por su definición de "inicio" como RunAtLoad o CalendarInterval .

Además, el matiz aquí es cuando la tarea comenzó . Bueno, eso depende de cuándo se haya configurado la tarea para que se inicie. El hecho de que la definición del trabajo esté cargada no significa que la tarea se haya iniciado.

Si define el trabajo en la definición del trabajo mediante Program y ProgramArguments puede teóricamente, hacer lo que quieras. Sin embargo, no hay lógica script; es sólo un comando y sus argumentos.

Ahora bien, si su scripttoma tiempo o para decirlo de otra manera, sigue siendo corriendo La modificación de la misma provocará, por supuesto, errores. Esto sería como si ejecutaras tu script, y luego simultáneamente en otra sesión de bash lo modificaras. Va a tener problemas.

launchd simplemente ejecuta el script como lo haría si escribiera el comando manualmente.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X