Chiamare più script bash ed eseguirli in parallelo, non in sequenza


19

Supponiamo che io ho tre (o più) script bash: script1.sh, script2.sh, e script3.sh. Vorrei chiamare tutti e tre questi script ed eseguirli in parallelo . Un modo per farlo è semplicemente eseguire i seguenti comandi:

nohup bash script1.sh &
nohup bash script2.sh &
nohup bash script3.sh &

(In generale, il completamento degli script potrebbe richiedere diverse ore o giorni, quindi vorrei usarlo in nohupmodo che continuino a funzionare anche se la mia console si chiude.)

Ma c'è un modo per eseguire quei tre comandi in parallelo con una singola chiamata?

Stavo pensando a qualcosa del genere

nohup bash script{1..3}.sh &

ma questo sembra eseguire script1.sh, script2.she script3.shin sequenza, non in parallelo.


2
Che cosa significa "chiamata singola"?
jw013,

1
Qual è il caso d'uso? Hai un milione di script per iniziare?
l0b0

@ jw013 Voglio dire, qualcosa come un comando a linea breve. Se ho 100 script per iniziare, vorrei poter digitare qualcosa di breve (come nohup bash script{1..100}.sh &o for i in {1..100}; do nohup bash script{1..100} &; done), anziché digitare nohup bash script*.sh &100 volte diverse.
Andrew,

1
Nel caso in cui gli script abbiano un output utile: puoi avviarli anche all'interno screen(o tmux), al fine di risolvere il problema della console ma mantenere l'accesso all'output (e all'input).
Hauke ​​Laging,

1
Non c'è nulla che ti impedisca di digitare tutti e 3 questi comandi nella stessa riga. nohup ... & nohup ... & nohup ... &. Se intendi invece che vuoi eseguire tutti gli script senza digitare ogni nome di script singolarmente, un semplice ciclo lo farà.
jw013,

Risposte:



14

Un modo migliore sarebbe usare GNU Parallel . GNU parallel è semplice e con esso possiamo controllare il numero di lavori da eseguire in parallelo con un maggiore controllo sui lavori.

Nel comando seguente, script{1..3}.shviene espanso e vengono inviati come argomenti bashin parallelo. Qui -j0indica che devono essere eseguiti quanti più lavori possibile. Per impostazione predefinita, parallelesegue un processo per un core CPU.

$ parallel -j0 bash :::: <(ls script{1..3}.sh)

E puoi anche provare a usare

$ parallel -j0 bash ::: script{1..3}.sh

Durante l'esecuzione del secondo metodo se ricevi un messaggio di errore, significa che l' --tollefopzione è impostata /etc/parallel/confige che deve essere eliminata e tutto funzionerà correttamente.

Puoi leggere la GNU Parallelspagina man qui per opzioni più ricche.

E nel caso in cui i lavori vengano eseguiti da una macchina remota, utilizzare meglio in screenmodo che la sessione non venga chiusa a causa di problemi di rete. nohupnon è necessario, poiché le versioni recenti di bash arrivano con huponexitas offe questo impedirà alla shell genitore di inviare HUPsegnali ai suoi figli durante la sua uscita. Nel caso in cui non sia disinserito, fallo con

$ shopt -u huponexit  

Se hai intenzione di usare bashcome la shell parallel -j0 bash :::: <(ls script{1..3}.sh)può essere ridotta a parallel -j0 bash :::: script{1..3}.sh, no?
Iruvar,

No, non è vero, quando '::::' è usato in parallelo significa che l'argomento è un file che contiene i comandi da eseguire e non il comando stesso. Qui stiamo usando la sostituzione del processo per reindirizzare i nomi degli script all'interno di un descrittore di file.
Kannan Mohan,

Ehm ... in quel caso perché no parallel -j0 bash ::: script{1..3}.sh?
Iruvar,

E ' bash ::: script{1..3}.shstata passata parallel, non è ::: script{1..3}.sh. Quindi questo dovrebbe espandi a parallel bash ::: script1.sh script2.sh script3.shdalla shell e poi parallelinvocazioni bash script1.sh, bash script2.sh, bash script3.sh. L'ho provato
iruvar il

1
No, non sono confuso, tutto quello che sto affermando è che il problema del PO è meglio risolto parallel -j0 bash ::: script{1..3}.sh- questo è meglio ::::dell'approccio poiché evita la necessità di sostituire il processo. Anche l' analisi dell'output è
piena di

9

Possiamo anche usare xargsper eseguire più script in parallelo.

$ ls script{1..5}.sh|xargs -n 1 -P 0 bash

qui ogni script viene passato a bash come argomento separatamente. -P 0indica che il numero di processi paralleli può essere il più possibile. È anche più sicuro che usando bash default job control feature (&).


5

Una soluzione a linea singola :

$ nohup bash script1.sh & nohup bash script2.sh & nohup bash script3.sh &

Meno facetiously, basta usare uno script wrapper:

$ cat script.sh
#!/usr/bin/env bash
script1.sh &
script2.sh &
script3.sh &
$ nohup script.sh &

Oppure passaci sopra:

for script in dir/*.sh
do
    nohup bash "$script" &
done

2

Se stai cercando di risparmiare un po 'di sforzo di battitura

eval "nohup bash "script{1..3}.sh" &"

O ripensandoci, forse no


1

Dai un'occhiata a questo strumento: https://github.com/wagoodman/bashful

Di 'che hai mytasks.yamlcon

tasks:
    - name: A title for some tasks
      parallel-tasks:
        - cmd: ./script1.sh
        - cmd: ./script2.sh -x an-arg
        - cmd: ./script3.sh -y some-other-arg

E lo esegui così:

nohup bashful run mytasks.yaml

I tuoi script verrebbero eseguiti in parallelo con una barra di avanzamento verticale (+ eta se l'hai già eseguita prima e il tempo è deterministico). Puoi modificare il numero di attività che desideri eseguire in parallelo se inizi a eseguire più di un semplice 3 qui:

config:
    max-parallel-commands: 6
tasks:
    ...

Disclaimer: sono l'autore.


0

Sto suggerendo un'utilità molto più semplice che ho appena scritto. Attualmente è chiamato par, ma presto verrà rinominato in parl o pll, non ho ancora deciso.

https://github.com/k-bx/par

L'API è semplice come:

par "script1.sh" "script2.sh" "script3.sh"

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.