Execute scripts Bash na pasta, tudo ao mesmo tempo

10

Vamos supor que eu tenha cinco .shscripts Bash ( ) em uma pasta ( my_folder) e eles sejam nomeados da seguinte maneira:

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

Como posso escrever um sexto script Bash ou apenas um liner que começará a executar todos esses scripts juntos?

Eu preciso dos cinco scripts para começar a executar todos juntos ao mesmo tempo e não um após o outro.

aaaaa
fonte

Respostas:

12

O GNU parallelé perfeito para esse tipo de coisa. Instale com sudo apt install parallele, em seguida:

parallel -j0 ::: my_folder/*sh

Os -jcontroles quantos processos t correm em paralelo, e -j0significa "todos eles". Defina-o com outro valor (por exemplo -j20) para executar os scripts em lotes.

Terdon
fonte
1
nota: existe também o parallelcomando do moreutilspacote. O exemplo de uso: parallel -j 20 -- my_folder/*.sh(Diferentemente do GNU parallel, -j0os scripts eram executados um de cada vez).
JFS
1
@jfs bom ponto. Mas observe que sudo apt install parallelsubstituirá o arquivo /usr/bin/parallelpelo do paralelo GNU. Portanto, desde que você o instale, como sugere minha resposta, deve funcionar conforme o esperado.
terdon 7/07/19
Sim, eu descobri da maneira mais difícil ao tentar parallelcomandos sem êxito do manual enquanto escrevia minha resposta para sugerir o GNU paralelo.
JFS
9

Para executar todos os scripts ao mesmo tempo (em paralelo), use:

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

Para executar um após o outro (sequencialmente), use:

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

Aprimoramento para comentários

Se você possui 200 scripts que deseja executar ao mesmo tempo (o que pode atolar a máquina BTW), use este script:

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

Defina os atributos de script como executáveis ​​com o comando:

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

Na primeira vez em que você executar o script, ele fará eco apenas dos nomes dos 200 scripts que estará executando. Quando estiver satisfeito, os nomes certos serão selecionados, edite o script e altere esta linha:

    echo bash "$Script" &

para:

    bash "$Script" &

Há três maneiras de chamar um script bash de outro, conforme respondido aqui:

  1. Torne o outro script executável, adicione a #!/bin/bashlinha na parte superior e o caminho em que o arquivo está para a $PATHvariável de ambiente. Então você pode chamá-lo como um comando normal;

  2. Ou chamá-lo com o comando fonte (alias é.) Como este: source /path/to/script;

  3. Ou usar o comando bash para executá-lo: /bin/bash /path/to/script;

No caso do OP, um ou mais dos 200 scripts não continham a #!/bin/bashprimeira linha shebang no arquivo. Como tal, a opção 3. teve que ser usada.


200 scripts em execução ao mesmo tempo

Um comentário foi levantado sobre se eles estão "rodando ao mesmo tempo". Em um sistema típico de 8 CPUs, 25 scripts compartilharão uma CPU ao mesmo tempo, mas apenas um script será executado por vez até que o intervalo de tempo (medido em milissegundos) se esgote. Em seguida, o próximo trabalho receberá sua parte justa de milissegundos, depois o próximo trabalho, etc., etc.

Em termos gerais, podemos dizer que 200 trabalhos estão sendo executados "simultaneamente", mas não "simultaneamente" em 8 CPUs, o que equivale a 25 trabalhos por CPU:

thread states.png

Imagem acima e comentários abaixo do planejador do kernel do Linux

time slice.png

WinEunuuchs2Unix
fonte
obrigado .. o problema é que, no meu caso real, tenho mais de 200 scripts para executar. então existe alguma maneira de executar todos eles com um único comando (ou seja, sem escrever os nomes dos arquivos)?
Aaaaa
@aaaaa Alterei a resposta para 200 scripts.
WinEunuuchs2Unix
obrigado. funciona .. a única coisa que tive que adicionar à sua última linha foi 'bash'. caso contrário, recebo 'permissão negada'.
aaaaa
1
@aaaaa Você realmente prefere que todos os mais de 200 scripts sejam executados ao mesmo tempo ou prefere que um número menor (digamos, 10) seja executado por vez, com os outros na fila para serem executados quando um ou mais deles terminar e o número de scripts em execução no momento cai abaixo desse número? (Se você estiver interessado em tais soluções, sugiro editar sua pergunta com informações sobre quantos scripts você possui, quanto tempo eles levam para serem executados, que tipo de trabalho eles fazem e assim por diante.)
Eliah Kagan
@aaaaa Obrigado pelo feedback. Atualizei a resposta para incluir o bashprefixo da chamada do script.
WinEunuuchs2Unix 07/07/19
3

Existe uma ferramenta para isso, leia man run-parts.

Por exemplo, eu faço:

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

no meu script de backup do Palm Pilot. ${visorhome}/pbackup.d/:

01PopulateJpilot  02Extract_Pedometer  03URLs  04google  05Books  06Weight  07Sec  08Bkgm 50hardlinks
waltinator
fonte
1
@ eliah-kagan A execução de "mais de 200 scripts" "ao mesmo tempo" parece imprudente. Pode ser uma boa maneira de teste de estresse de um sistema
waltinator
Bom ponto. Eu acho que você ainda pode mencionar que run-partsexecuta os scripts sequencialmente em vez de todos de uma vez, conforme solicitado pelo OP. Você está certo, no entanto, que é improvável que a execução de 200 scripts de uma só vez execute o mesmo que a execução de 5 - e mesmo que executá-los todos de uma vez não cause problemas, ainda pode ser desnecessário. Eu comentou a sugerir o OP esclarecer suas preferências quanto a isso.
Eliah Kagan 07/07/19
run-partsnão executará os scripts (eles têm um ponto no nome:my_folder/*.sh
jfs
1
run-partstem requisitos de nome de arquivo muito específicos por algum motivo estranho. Ele não inicia nomes de arquivos com extensões, então, temo que isso não funcione aqui.
terdon 7/07
1

Para executar todos os *.shscripts no my_folderdiretório ao mesmo tempo usando xargs:

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

Para limitar o número de scripts executados simultaneamente 10:

$ ls my_folder/*.sh | xargs -P10 -n1 bash
jfs
fonte
É uma prática ruim usar a saída de lsem um script. Usar findé muito mais seguro. É o primeiro item aqui: mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29
Joe
@ Joe em geral, é verdade. Não vejo problemas nesse caso em particular.
JFS
Isso porque você já sabe disso. As pessoas que vêm aqui mais tarde podem não.
Joe
@ Joe não segue o dogma às cegas. Pense por si mesmo que uma opção é melhor que outra, o que são compensações no seu caso.
JFS
Não é um dogma. Eu sou alérgico a eles. Mas eu vi as coisas que eu posso emitir. A análise da saída legível por humanos não é confiável. Não há incentivos para os desenvolvedores para manter
Joe