execute um script em várias pastas em paralelo

execute um script em várias pastas em paralelo

Eu tenho vários subdiretórios em um diretório de alto nível. Cada subdiretório possui vários arquivos e um script de shell de loop for. O mesmo script de loop for está presente em cada subdiretório. Quero entrar em cada subdiretório e executar o script for loop em paralelo em vários terminais. Eu tentei isso, mas parece funcionar em série (um após o outro), mas quero executar todos eles em paralelo.

find dir_* -type f -execdir sh for_loop.sh {} \;

Responder1

Supondo que isso faça a coisa certa - apenas em série:

find dir_* -type f -execdir sh for_loop.sh {} \;

Então você poderá substituir isso por:

find dir_* -type f | parallel 'cd {//} && sh for_loop.sh {}'

Para executá-lo em vários terminais, GNU Parallel suporta tmuxa execução de cada comando em seu próprio tmuxpainel:

find dir_* -type f | parallel --tmuxpane 'cd {//} && sh for_loop.sh {}'

O padrão é um trabalho por núcleo da CPU. No seu caso, você pode querer executar mais um trabalho do que os núcleos:

 find dir_* -type f | parallel -j+1 --tmuxpane 'cd {//} && sh for_loop.sh {}'

GNU Parallel é um paralelizador geral e facilita a execução de trabalhos em paralelo na mesma máquina ou em várias máquinas às quais você tem acesso ssh.

Se você tiver 32 jobs diferentes que deseja executar em 4 CPUs, uma maneira simples de paralelizar é executar 8 jobs em cada CPU:

Agendamento simples

Em vez disso, o GNU Parallel gera um novo processo quando um deles termina - mantendo as CPUs ativas e economizando tempo:

Agendamento paralelo GNU

Instalação

Por razões de segurança você deve instalar o GNU Parallel com seu gerenciador de pacotes, mas se o GNU Parallel não estiver empacotado para sua distribuição, você pode fazer uma instalação pessoal, que não requer acesso root. Isso pode ser feito em 10 segundos fazendo o seguinte:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh

Para outras opções de instalação consultehttp://git.savannah.gnu.org/cgit/parallel.git/tree/README

Saber mais

Veja mais exemplos:http://www.gnu.org/software/parallel/man.html

Assista aos vídeos de introdução:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Percorra o tutorial:http://www.gnu.org/software/parallel/parallel_tutorial.html

Inscreva-se na lista de e-mail para obter suporte:https://lists.gnu.org/mailman/listinfo/parallel

Responder2

Provavelmente a ferramenta perfeita para isso éParalelo GNU:

parallel ::: dir_*/for_loop.sh

O GNU Parallel não apenas executa cada trabalho em paralelo, mas também demultiplexa sua saída para que não interfiram entre si.

Em sua página de manual:

GNU paralelo é uma ferramenta shell para executar trabalhos em paralelo usando um ou mais computadores. Um trabalho pode ser um único comando ou um pequeno script que deve ser executado para cada uma das linhas da entrada. A entrada típica é uma lista de arquivos, uma lista de hosts, uma lista de usuários, uma lista de URLs ou uma lista de tabelas. Um trabalho também pode ser um comando que lê um canal. O paralelo GNU pode então dividir a entrada em blocos e canalizar um bloco para cada comando em paralelo.

Se você usa xargs e tee hoje, achará o GNU paralelo muito fácil de usar, pois o GNU paralelo foi escrito para ter as mesmas opções do xargs. Se você escrever loops no shell, descobrirá que o GNU paralelo pode substituir a maioria dos loops e fazê-los rodar mais rápido, executando vários trabalhos em paralelo.

O paralelo GNU garante que a saída dos comandos seja a mesma que você obteria se executasse os comandos sequencialmente. Isso torna possível usar a saída do GNU paralelo como entrada para outros programas.

Responder3

findnão fará isso por você.

crie um script, localize seus scripts for_loop.sh e execute-os, assim:

#!/bin/bash

for theScript in $(find dir_* -name for_loop.sh); do
  "$theScript" &
done

se o script tiver que ser executado dentro do subdiretório, tente cdantes, talvez como cd $(dirname "$theScript") && . $(basename "$theScript").

meus exemplos não são testados em detalhes e não são tolerantes a erros...

Editar 1:

ComoSato Katsuracomentado corretamente, o script acima quebra se houver espaços no nome do diretório.

Então mudei para fazer um loop para read:

#!/bin/bash
find dir_* -name for_loop.sh | while IFS= read -r theScript; do
  "$theScript" &
done

Responder4

você pode fazer a partir do seu diretório de nível superior

for D in `find . -type d -maxdepth 1`
do 
     $D/<yourScriptName>.sh &
done

o "&" é para executá-los em segundo plano

informação relacionada