pausar un script bash hasta que los comandos anteriores hayan terminado

Tengo un script bash que se parece a lo siguiente:

##script #!/bin/bash rm data* rm logfile* for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done 

Me gustaría crear otro bucle for después del primero para continuar por otros 30. Por ejemplo

##script #!/bin/bash rm data* rm logfile* for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & for i in {31..60} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done 

Me gustaría finalice el primer conjunto de trabajos antes de iniciar el nuevo conjunto. Pero debido al nohup parece que todos se ejecutan simultáneamente.

Tengo nohup porque me conecto de forma remota a mi servidor e inicio los trabajos allí y luego cierro mi bash. ¿Existe una solución alternativa?

Comentarios

  • Busque en el manual el wait incorporado.

Responder

Deberá utilizar el comando wait para Haga esto por usted. Puede capturar todos los ID de procesos secundarios y esperarlos específicamente, o si son los únicos procesos en segundo plano que está creando su secuencia de comandos, puede simplemente llamar a wait sin un argumento. Por ejemplo:

#!/bin/bash # run two processes in the background and wait for them to finish nohup sleep 3 & nohup sleep 10 & echo "This will wait until both are done" date wait date echo "Done" 

Respuesta

Algunos puntos:

  • Si su objetivo con nohup es evitar que una salida remota de shell elimine sus procesos de trabajo, debe usar nohup en el script en sí, no en los procesos de trabajo individuales que crea.

  • Como se explica aquí , nohup solo evita que los procesos reciban SIGHUP y de interactuar con el terminal, pero no rompe la relación entre el shell y sus procesos secundarios.

  • Debido al punto anterior, con o sin nohup, un wait simple entre los dos for bucles provocará el segundo for para ejecutarse solo después de que todos los procesos secundarios iniciados por el primer for hayan salido.

  • Con un wait:

    se esperan todos los procesos secundarios actualmente activos y el estado de retorno es cero.

  • Si necesita ejecutar el segundo for solo si no hubo errores en el primero , luego deberá guardar cada PID de trabajador con $! y pasarlos todos a wait:

    pids= for ... worker ... & pids+=" $!" done wait $pids || { echo "there were errors" >&2; exit 1; } 

Comentarios

  • Hay pu Serían otros trabajos ejecutándose en el servidor. Así que ' solo quiero esperar mi lote … son scripts R, por lo que se ejecutan bajo R o cc1plus en el top comando
  • También ' me gustaría usar nohup dentro para ejecutar todos los comandos en " paralelo ". básicamente se trata de simulaciones para un programa científico. Quiero ejecutar 180 simulaciones en total, pero en lotes de 60. El contador también debe ir de 1 a 180. Si las hago una a la vez, tomará demasiado tiempo.
  • wait hace que bash espere los trabajos en segundo plano que generó, nada más. Puede haber algo de confusión aquí: estos for bucles, ¿los guardó en un archivo y los invocó como un script (lo que asumí, debido al ##script línea), o los está escribiendo a mano en la terminal?
  • Estaba haciendo cat file.txt | while y los pids no se establecieron fuera del bucle por lo que el comando de espera vio una cadena $pids vacía. por qué sucede esto se explica en serverfault.com/q/259339 . se corrige fácilmente como while ... < files.txt como se responde en serverfault.com/a/259346
  • Solo por curiosidad ¿Cuál es el propósito del signo + con la variable pids?

Responder

Use el fg incorporado. Espera hasta que finalicen los procesos en segundo plano.

Intente help fg para obtener más detalles.

Comentarios

  • Un script se ejecuta sin control de trabajo.

Responder

Si inserta algo como el siguiente segmento de código entre los dos bucles for, podría ayudar.

flag=0 while [ flag -eq 0 ] do ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null flag=${?} sleep 10 done 

Por supuesto, si su aplicación Rscript tiene la posibilidad de no completarse correctamente y demorarse, es posible que su segundo bucle for no tenga la oportunidad de ejecutarse. El segmento de código anterior asume que todos los procesos con el identificador Rscript --vanilla se completarán y desaparecerán correctamente. Sin saber qué hace su aplicación y cómo se ejecuta, tengo que confiar en esta suposición.

EDIT

A la luz de los comentarios, esto encajaría mejor tus necesidades. (incluye su código original y la lógica de verificación de finalización)

for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & pids[$i]=${!} done flag=0 while [ flag -eq 0 ] do for PID in $(echo ${pids[@]}) do flag=1 ps -ef | grep ${PID} | grep -v grep >/dev/null; r=${?} if [ ${r} -eq 0 ] then flag=0 fi done done for i in {31..60} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done 

Comentarios

  • El proceso El nombre en top muestra R a veces o cc1plus.
  • En ese caso, necesitará encontrar un denominador común, que aparezca en la lista ps -ef. O después de cada comando nohup, registre el PID en una variable (preferiblemente una matriz) por echo ${!} y verifique este grupo de PID. Cuando desaparezcan todos, puede continuar con el segundo for bucle

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *