Bash: Múltiple para bucles en segundo plano.

8

¿Es esta la forma correcta de iniciar múltiples procesamientos secuenciales en segundo plano?

for i in {1..10}; do
    for j in {1..10}; do
        run_command $i $j;
    done &
done;

Todos jdeben procesarse uno tras otro para un determinado i, pero todos ideben procesarse simultáneamente.

Controlado por radio
fuente
¿Qué quieres decir con "forma correcta"?
Eran Ben-Natan
Principalmente que funciona. Me faltaba esto en stackoverflow.
Radio controlado el
1
:-) Estoy preguntando porque tu código funciona bien para mí. Si por "forma correcta" te refieres a las mejores prácticas, entonces pondría el bucle interno en una función o incluso en un archivo diferente para que sea más claro
Eran Ben-Natan

Respuestas:

8

El bucle externo que tienes es básicamente

for i in {1..10}; do
    some_compound_command &
done

Esto comenzaría diez instancias simultáneas de some_compound_commanden segundo plano. Comenzarán lo más rápido posible, pero no "todo al mismo tiempo" (es decir, si some_compound_commandtoma muy poco tiempo, entonces el primero bien puede terminar antes de que comience el último).

El hecho de que some_compound_commandsea ​​un bucle no es importante. Esto significa que el código que muestra es correcto en que las iteraciones del jbucle interno se ejecutarán secuencialmente, pero todas las instancias del bucle interno (una por iteración del ibucle externo ) se iniciarían simultáneamente.

Lo único a tener en cuenta es que cada trabajo en segundo plano se ejecutará en una subshell. Esto significa que los cambios realizados en el entorno (p. Ej., Modificaciones en los valores de las variables de shell, cambios en el directorio de trabajo actual con cd, etc.) en una instancia del bucle interno no serán visibles fuera de ese trabajo en segundo plano en particular.

Lo que quizás desee agregar es una waitdeclaración después de su ciclo, solo para esperar a que todos los trabajos en segundo plano realmente finalicen, al menos antes de que finalice el script:

for i in {1..10}; do
    for j in {1..10}; do
        run_command "$i" "$j"
    done &
done

wait
Kusalananda
fuente
3

Si tiene GNU Parallel, haría:

parallel -j0 'for j in {1..10}; do run_command {} $j; done' ::: {1..10}

Uno de los beneficios es que la salida de la ejecución en paralelo run_commandsno se mezclará.

Ole Tange
fuente