Ejecute scripts de Bash en la carpeta, todo al mismo tiempo.

10

Supongamos que tengo cinco .shscripts Bash ( ) en una carpeta ( my_folder), y se nombran de la siguiente manera:

script_1.sh
script_2.sh
script_3.sh
script_4.sh
script_5.sh

¿Cómo puedo escribir una sexta secuencia de comandos Bash o solo una línea que comenzará a ejecutar todas estas secuencias de comandos juntas?

Necesito los cinco scripts para comenzar a ejecutarse todos juntos al mismo tiempo y no uno tras otro.

aaaaa
fuente

Respuestas:

12

GNU paralleles perfecto para este tipo de cosas. Instalar con sudo apt install parallely luego:

parallel -j0 ::: my_folder/*sh

Los -jcontroles cuántos procesos t correr en paralelo, y -j0significa "todos ellos". Ajústelo a otro valor (p -j20. Ej. ) Para ejecutar los scripts en lotes.

terdon
fuente
1
nota: también existe el parallelcomando del moreutilspaquete. El ejemplo de uso: parallel -j 20 -- my_folder/*.sh(A diferencia de GNU parallel, -j0ejecutaría los scripts de uno en uno).
jfs
1
@jfs buen punto. Pero tenga en cuenta que sudo apt install parallelreemplazará el archivo /usr/bin/parallelcon el de GNU paralelo. Entonces, siempre que lo instale, como sugiere mi respuesta, debería funcionar como se esperaba.
terdon
Sí, lo descubrí por las malas cuando intenté sin éxito los parallelcomandos del manual mientras escribía mi respuesta para sugerir GNU en paralelo.
jfs
9

Para ejecutar todos los scripts al mismo tiempo (en paralelo) use:

script_1.sh &
script_2.sh &
script_3.sh &
script_4.sh &
script_5.sh &

Para ejecutar el uno después del otro (secuencialmente) use:

script_1.sh &&
script_2.sh &&
script_3.sh &&
script_4.sh &&
script_5.sh

Mejora para comentarios

Si tiene 200 scripts que desea ejecutar al mismo tiempo (lo que podría atascar la máquina, por cierto) use este script:

#!/bin/bash
for Script in my_folder/*.sh ; do
    echo bash "$Script" &
done

Establezca los atributos del script en ejecutable con el comando:

chmod a+x /path/to/script.sh

La primera vez que ejecute el script, solo hará eco de los nombres de los 200 scripts que ejecutará. Cuando esté contento de haber seleccionado los nombres correctos, edite el script y cambie esta línea:

    echo bash "$Script" &

a:

    bash "$Script" &

Hay tres formas en que puede llamar a un script bash desde otro como se responde aquí:

  1. Haga que el otro script sea ejecutable, agregue la #!/bin/bashlínea en la parte superior y la ruta donde está el archivo a la $PATHvariable de entorno. Entonces puedes llamarlo como un comando normal;

  2. O llámelo con el comando de origen (alias es.) Así source /path/to/script:;

  3. O utilice el comando bash para ejecutarlo: /bin/bash /path/to/script;

En el caso de OP, uno o más de los 200 scripts no contenían la #!/bin/bashprimera línea shebang en el archivo. Como tal, la opción 3. tuvo que ser utilizada.


200 secuencias de comandos que se ejecutan al mismo tiempo

Se ha planteado un comentario sobre si están "ejecutándose al mismo tiempo". En un sistema típico de 8 CPU, 25 scripts compartirán una CPU al mismo tiempo, pero solo se ejecutará un script a la vez hasta que se agote el tiempo (medido en milisegundos). Luego, el próximo trabajo recibirá su parte justa de milisegundos, luego el siguiente trabajo, etc., etc.

En términos generales, podemos decir que 200 trabajos se ejecutan "simultáneamente" pero no "simultáneamente" en 8 CPU, lo que equivale a 25 trabajos por CPU:

thread states.png

Imagen de arriba y comentarios a continuación del planificador del kernel de Linux

time slice.png

WinEunuuchs2Unix
fuente
gracias ... la cosa es que en mi caso real tengo más de 200 scripts para ejecutar. Entonces, ¿hay alguna manera de que pueda ejecutarlos todos con un solo comando (es decir, sin escribir sus nombres de archivo)?
aaaaa
@aaaaa He cambiado la respuesta para 200 scripts.
WinEunuuchs2Unix
Gracias. funciona ... lo único que tuve que agregar a su última línea fue 'bash'. de lo contrario recibo 'permiso denegado'.
aaaaa
1
@aaaaa ¿Realmente prefiere que se ejecuten todos los más de 200 scripts al mismo tiempo, o prefiere que se ejecute un número menor (digamos, 10) a la vez, con los otros en cola para ejecutarse cuando uno o más de ellos finalicen y ¿el número de scripts actualmente en ejecución cae por debajo de ese número? (Si está interesado en tales soluciones, le sugiero que edite su pregunta con información sobre cuántos scripts tiene, cuánto tiempo demoran en ejecutarse, qué tipo de trabajo hacen, etc.)
Eliah Kagan
@aaaaa Gracias por los comentarios. He actualizado la respuesta para incluir el bashprefijo para llamar al script.
WinEunuuchs2Unix
3

Hay una herramienta para esto, lee man run-parts.

Por ejemplo, yo hago:

 run-parts ${visorhome}/pbackup.d/

en mi script de copia de seguridad Palm Pilot. ${visorhome}/pbackup.d/:

01PopulateJpilot  02Extract_Pedometer  03URLs  04google  05Books  06Weight  07Sec  08Bkgm 50hardlinks
Waltinator
fuente
1
@ eliah-kagan Ejecutar "más de 200 guiones" "al mismo tiempo" parece imprudente. Podría ser una buena manera de hacer una prueba de esfuerzo en un sistema
waltinator
Buen punto. Creo que es posible que aún desee mencionar que run-partsejecuta los scripts secuencialmente en lugar de todos a la vez como lo solicitó el OP. Sin embargo, tiene razón, es probable que ejecutar 200 scripts a la vez no tenga el mismo rendimiento que ejecutar 5, e incluso si ejecutarlos todos a la vez no causa ningún problema, aún puede ser innecesario. He comentado sugerir que el OP aclare sus preferencias a este respecto.
Eliah Kagan
run-partsno ejecutará los scripts (tienen un punto en el nombre:my_folder/*.sh
jfs
1
run-partstiene requisitos de nombre de archivo muy específicos por alguna extraña razón. No lanzará nombres de archivo con extensiones, así que me temo que esto no funcionará aquí.
terdon
1

Para ejecutar todos los *.shscripts en el my_folderdirectorio al mismo tiempo usando xargs:

$ ls my_folder/*.sh | xargs -P0 -n1 bash

Para limitar el número de scripts ejecutados simultáneamente a 10:

$ ls my_folder/*.sh | xargs -P10 -n1 bash
jfs
fuente
Es una mala práctica usar la salida de lsun script. Usar findes mucho más seguro. Es el primer elemento aquí: mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29
Joe
@ Joe en general, es cierto. No veo problemas en este caso particular.
jfs
Eso es porque ya lo sabes. La gente que viene más tarde podría no hacerlo.
Joe
@ Joe no sigue el dogma a ciegas. Piensa por ti mismo que una opción es mejor que otra, ¿cuáles son las compensaciones en tu caso?
jfs
No es un dogma. Soy alérgico a esos. Pero he visto las cosas que ls puede emitir. Analizar la salida legible por humanos no es confiable. No hay ningún incentivo para los desarrolladores
Joe