¿Cómo espero que un programa se inicie en otro shell?

20

Tengo un programa que realiza una gran cantidad de trabajo (toma alrededor de 4 a 5 horas) que inicia cron cuando todos los datos con los que trabaja están disponibles. A veces, cuando espero que termine, me gustaría poder iniciar otro programa (interactivo) cuando finalice. la llamada de espera parece prometedora pero solo esperará a los niños.

hildred
fuente
El único otro método que puedo concebir es crear un archivo a partir de cronjob, y luego usar inotifywait en ese proceso, cuando los archivos eliminados, puede comenzar su segundo proceso (ejecutar inotifywait).
slm
Creo que podría hacer algo en este sentido utilizando ipctambién la comunicación entre procesos. man ipc.
slm
Aunque no está viendo un servicio para reiniciarlo, Dios, Monit o uno de los otros paquetes mencionados en estas preguntas y respuestas también harían el trabajo: unix.stackexchange.com/questions/75785/…
slm
@slm se puede usar inotify en cualquier sistema de archivos, por ejemplo, ¿esperar en close_write en / proc / _pid_ / fd / 1?
hildred
No del todo seguro, pero esa podría ser otra forma de hacerlo 8-). Hubo algunas Q que recuerdo donde había alguna nueva funcionalidad del kernel relacionada con el monitoreo de procesos similar al inotifywait (para archivos). Esta nueva característica era para eventos en proceso, pensé, pero muchas de las preguntas y respuestas comienzan a funcionar juntas en mi mente 8-). Creo que la A la proporcioné yo o Gilles.
slm

Respuestas:

13

Definitivamente prefiero la solución EDIT # 3 (ver más abajo).

Si no está en el mismo shell utilizan un mientras bucle con la condición en ps -p regresar cierto. Poner un sueño en el bucle para reducir el uso del procesador.

while ps -p <pid> >/dev/null 2>&1
do
   sleep 10
done 

o si su UNIX es compatible con / proc (por ejemplo, HP-UX todavía no lo hace).

while [[ -d /proc/<pid> ]]
do 
    sleep 10
done

Si quieres un tiempo de espera

timeout=6  # timeout after 1mn  
while ((timeout > 0)) && ps -p <pid> >/dev/null 2>&1
do
   sleep 10
   ((timeout -= 1))
done 

EDITAR # 1

Hay otra forma: no use cron . Use el comando por lotes para apilar sus trabajos.

Por ejemplo, podría apilar diariamente todos sus trabajos. El lote puede ajustarse para permitir cierto paralelismo para que un trabajo bloqueado no detenga toda la pila (depende del sistema operativo).

EDITAR # 2

Cree un fifo en su directorio de inicio:

$ mkfifo ~/tata

al final de tu trabajo:

echo "it's done" > ~/tata

Al comienzo del otro trabajo (el que está esperando):

cat ~/tata 

No está sondeando, es viejo bueno bloqueando IO.

EDITAR # 3

Usando señales:

Al comienzo de la secuencia de comandos que está esperando:

echo $$ >>~/WeAreStopped
kill -STOP $$

al final de tu largo trabajo:

if [[ -f ~/WeAreStopped ]] ; then
    xargs kill -CONT < ~/WeAreStopped
    rm ~/WeAreStopped
fi
Emmanuel
fuente
Encuesta, ¡qué asco! Buena decisión: perder el tiempo del procesador o mi tiempo para ajustar el sueño. Tiene que haber una mejor respuesta.
hildred
:) El sondeo es bueno para usted, el sondeo no tiene estado, el sondeo es confiable.
Emmanuel
el sondeo es lento, el sondeo desperdicia el tiempo del procesador.
hildred
Con un tiempo de ejecución de 0.01s, los 1440 ps ejecutados durante las 4 horas habrían consumido 14.4s. Mucho menos que un planificador que administra dependencias de trabajos: D
Emmanuel
Creo que esta es probablemente la mejor opción: stackoverflow.com/questions/1058047/… , aunque sea hacky.
slm
5

Puede modificar su trabajo cron para usar alguna bandera.

En lugar de

2  2 * * *           /path/my_binary

Puedes usar

2  2 * * *           touch /tmp/i_m_running; /path/my_binary; rm /tmp/i_m_running

Y solo monitoree este archivo en script o incluso manualmente. Si existe, entonces su programa se está ejecutando; de lo contrario, siéntase libre de hacer lo que quiera.

La muestra del script:

while [[ -f /tmp/i_m_running ]] ; do
   sleep 10 ;
done
launch_whatever_you_want

En caso de que no le guste usar sleep, puede modificar el script y ejecutarlo a través de cron una vez por X minutos.

En ese caso, la muestra del script será:

[[ -f /tmp/i_m_running ]] && { echo "Too early" ; exit ; }
launch_whatever_you_want

De esta manera es un poco más fácil, ya que no tiene que encontrar el PID de su proceso cron.

prisa
fuente
4

No hay ninguna facilidad para que un proceso espere a que termine otro proceso, excepto que un padre espere a que termine uno de sus procesos hijos. Si puede, inicie el programa a través de un script:

do_large_amount_of_work
start_interactive_program

Si no puede hacer eso, por ejemplo, antes de querer comenzar la gran cantidad de trabajo desde un trabajo cron pero el programa interactivo desde el contexto de su sesión, entonces haga esto

do_large_amount_of_work
notify_completion

Hay varias formas de implementar notify_completion. Algunos entornos de escritorio proporcionan un mecanismo de notificación ( puede ser útil abrir una ventana en una pantalla X remota (¿por qué "No se puede abrir la pantalla")? También puede hacer uno usando notificaciones de cambio de archivo. En Linux, la función de notificación de cambio de archivo es inotify .

do_large_amount_of_work
echo $? >/path/to/finished.stamp

Para reaccionar a la creación de /path/to/finished.stamp:

inotifywait -e close_write -q /path/to/finished.stamp
start_interactive_program

Si no puede cambiar la forma en que do_large_amount_of_workse invoca, pero sabe qué archivo modifica por última vez, puede usar el mismo mecanismo para reaccionar cuando se cierra ese archivo. También puede reaccionar a otros eventos, como el cambio de nombre de un archivo (consulte el inotifywaitmanual para obtener una lista de posibilidades).

Gilles 'SO- deja de ser malvado'
fuente
0

Haga que el cronjob active el script e invoque un script de shell vacío en el que puede insertar tareas de seguimiento si las necesita.

Es muy similar al enfoque de Gilles.

cronjob-task.sh contiene:

# do_large_amount_of_work

./post-execute.sh

donde post-execute.shgeneralmente está vacío, a menos que vea que necesita activar una tarea de seguimiento.

Daniel F
fuente