Esegui gli script Bash nella cartella contemporaneamente


10

Supponiamo che io abbia cinque .shscript Bash ( ) in una cartella ( my_folder) e che siano chiamati come segue:

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

Come posso scrivere un sesto script Bash o solo una riga che inizierà a eseguire tutti questi script insieme?

Ho bisogno che i cinque script inizino a funzionare tutti insieme contemporaneamente e non uno dopo l'altro.


Risposte:


12

GNU parallelè perfetto per questo genere di cose. Installa con sudo apt install parallele quindi:

parallel -j0 ::: my_folder/*sh

I -jcontrolli quanti processi t funzionano in parallelo, e -j0significa "tutti loro". Impostalo su un altro valore (ad es. -j20) Per eseguire invece gli script in batch.


1
nota: c'è anche il parallelcomando dal moreutilspacchetto. L'esempio di utilizzo: parallel -j 20 -- my_folder/*.sh(A differenza di GNU parallel, -j0eseguiva gli script uno alla volta).
jfs,

1
@jfs buon punto. Ma nota che sudo apt install parallelsostituirà il file /usr/bin/parallelcon quello di GNU parallel. Quindi, finché lo installi, come suggerisce la mia risposta, dovrebbe funzionare come previsto.
Terdon,

Sì, l'ho scoperto nel modo più difficile quando ho provato i parallelcomandi senza successo dal manuale mentre scrivevo la mia risposta per suggerire GNU parallel.
jfs,

9

Per eseguire tutti gli script contemporaneamente (in parallelo) utilizzare:

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

Per eseguire uno dopo l'altro (in sequenza) utilizzare:

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

Miglioramento per i commenti

Se hai 200 script che vuoi eseguire contemporaneamente (il che potrebbe impantanare la macchina in BTW) usa questo script:

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

Impostare gli attributi dello script su eseguibile con il comando:

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

La prima volta che esegui lo script, farà eco solo ai nomi dei 200 script che eseguirà. Quando sei soddisfatto, vengono selezionati i nomi giusti, modifica lo script e cambia questa riga:

    echo bash "$Script" &

per:

    bash "$Script" &

Esistono tre modi per chiamare uno script bash da un altro, come indicato qui:

  1. Rendi eseguibile l'altro script, aggiungi la #!/bin/bashriga in alto e il percorso in cui si trova il file nella $PATHvariabile di ambiente. Quindi puoi chiamarlo come un normale comando;

  2. Oppure chiamalo con il comando source (alias is.) In questo modo source /path/to/script:;

  3. Oppure utilizzare il comando bash per eseguirlo: /bin/bash /path/to/script;

Nel caso di OP uno o più dei 200 script non contenevano la #!/bin/bashprima riga di shebang nel file. Come tale opzione 3. doveva essere usato.


200 script in esecuzione contemporaneamente

È stato sollevato un commento sul fatto che siano "in esecuzione contemporaneamente". Su un tipico sistema a 8 CPU, 25 script condivideranno una CPU contemporaneamente, ma verrà eseguito solo uno script alla volta fino allo scadere del suo intervallo di tempo (misurato in millisecondi). Quindi il lavoro successivo riceverà la sua giusta quota di millisecondi, quindi il lavoro successivo, ecc., Ecc.

In termini allentati possiamo dire che 200 lavori sono in esecuzione "contemporaneamente" ma non "simultaneamente" su 8 CPU, il che equivale a 25 lavori per CPU:

thread states.png

Immagine sopra e commenti sotto dallo scheduler del kernel Linux

time slice.png


grazie..la cosa è che nel mio caso reale ho più di 200 script da eseguire. quindi c'è un modo per eseguirli tutti con un singolo comando (cioè senza scrivere i nomi dei file)?
aaaaa,

@aaaaa Ho cambiato la risposta per 200 script.
WinEunuuchs2Unix

Grazie. funziona .. l'unica cosa che ho dovuto aggiungere alla tua ultima riga era "bash". altrimenti ricevo "permesso negato".
aaaaa,

1
@aaaaa In realtà preferisci che tutti gli oltre 200 script vengano eseguiti contemporaneamente, o preferiresti avere un numero più piccolo (diciamo, 10) eseguito alla volta, con gli altri in coda per l'esecuzione quando uno o più di essi finiscono e il numero di script attualmente in esecuzione scende al di sotto di quel numero? (Se sei interessato a tali soluzioni, ti suggerisco di modificare la tua domanda con informazioni su quanti script hai, quanto tempo impiegano a correre, che tipo di lavoro fanno e così via.)
Eliah Kagan

@aaaaa Grazie per il feedback. Ho aggiornato la risposta per includere il bashprefisso alla chiamata dello script.
WinEunuuchs2Unix

3

C'è uno strumento per questo, leggi man run-parts.

Ad esempio, faccio:

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

nel mio script di backup di Palm Pilot. ${visorhome}/pbackup.d/:

01PopulateJpilot  02Extract_Pedometer  03URLs  04google  05Books  06Weight  07Sec  08Bkgm 50hardlinks

1
@ eliah-kagan L'esecuzione di "più di 200 script" "contemporaneamente" sembra poco saggia. Potrebbe essere un buon modo per sottoporre a stress test un sistema
waltinator

Buon punto. Penso che potresti ancora voler menzionare che run-partsesegue gli script in sequenza piuttosto che tutti in una volta, come richiesto dall'OP. Hai ragione, tuttavia, è improbabile che l'esecuzione di 200 script contemporaneamente esegua lo stesso funzionamento della 5 - e anche se eseguirli tutti in una volta non causa alcun problema, potrebbe non essere ancora necessario. Ho commentato per suggerire che il PO chiarire le loro preferenze al riguardo.
Eliah Kagan,

run-partsnon eseguirà gli script (hanno un punto nel nome:my_folder/*.sh
jfs

1
run-partsha requisiti di nome file molto specifici per qualche strana ragione. Non avvierà i nomi dei file con estensioni, quindi temo che non funzionerà qui.
terdon,

1

Per eseguire tutti gli *.shscript nella my_folderdirectory contemporaneamente usando xargs:

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

Per limitare il numero di script eseguiti contemporaneamente a 10:

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

È una cattiva pratica usare l'output di lsin uno script. L'uso findè molto più sicuro. È il primo articolo qui: mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29
Joe

@Joe in generale, è vero. Non vedo problemi in questo caso particolare.
jfs,

Questo perché lo sai già. Le persone che vengono qui dopo potrebbero non esserlo.
Joe,

@Joe non segui il dogma alla cieca. Pensa per te che un'opzione è meglio di un'altra quali sono i compromessi nel tuo caso.
jfs,

Non è un dogma. Sono allergico a quelli. Ma ho visto le cose che possiamo emettere. L'analisi dell'output leggibile dall'uomo non è affidabile. Non c'è incentivo per gli sviluppatori a mantenere
Joe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.