executa um script em várias pastas em paralelo

5

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

find dir_* -type f -execdir sh for_loop.sh {} \;
    
por user233520 29.05.2017 / 09:07

5 respostas

4

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 desmultiplexa sua saída para que eles não interfiram uns com os outros.

De sua página de manual:

GNU parallel is a shell tool for executing jobs in parallel using one or more computers. A job can be a single command or a small script that has to be run for each of the lines in the input. The typical input is a list of files, a list of hosts, a list of users, a list of URLs, or a list of tables. A job can also be a command that reads from a pipe. GNU parallel can then split the input into blocks and pipe a block into each command in parallel.

If you use xargs and tee today you will find GNU parallel very easy to use as GNU parallel is written to have the same options as xargs. If you write loops in shell, you will find GNU parallel may be able to replace most of the loops and make them run faster by running several jobs in parallel.

GNU parallel makes sure output from the commands is the same output as you would get had you run the commands sequentially. This makes it possible to use output from GNU parallel as input for other programs.

    
por 29.05.2017 / 10:47
3

find não fará isso por você.

crie um skript, localize seus scripts do 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 cd antes, 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:

Como Sato Katsura comentou corretamente, o script acima quebra se houver espaços no nome do diretório.

Então mudei para loop para read :

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

Assumindo que isso faz a coisa certa - apenas em série:

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

Então você deve poder substituir isso por:

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

Para executá-lo em vários terminais, o GNU Parallel suporta tmux para executar cada comando em seu próprio painel tmux :

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 {}'

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

Se você tem 32 tarefas diferentes que você quer rodar em 4 CPUs, uma maneira direta de paralelizar é rodar 8 tarefas em cada processador:

OGNUParallelgeraumnovoprocessoquandoumtermina-mantendoasCPUsativaseeconomizandotempo:

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 ao fazer isso:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

Para outras opções de instalação, consulte o link

Saiba mais

Veja mais exemplos: link

Assista aos vídeos de introdução: link

Percorra o tutorial: link

Inscreva-se na lista de e-mail para obter suporte: link

    
por 29.05.2017 / 20:21
2

Você deve passar a saída de find para xargs , em execução no modo paralelo:

find dir_*/ -type f -name for_loop.sh -print0 | xargs -0 -r -n 1 -P 3 -t sh

Estamos pedindo a find para encontrar todos os arquivos com nomes de for_loop.sh recursivamente sob os diretórios que começam com os nomes dir_ e passá-los para xargs, um arquivo de cada vez, no modo paralelo de executar não mais que 3 processos a qualquer momento.

O uso é feito do delimitador nulo find na impressão de nomes de arquivos por xargs e sua divisão em valores nulos por %code% .

    
por 29.05.2017 / 10:07
0

você pode fazer no seu diretório de nível superior

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

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

    
por 29.05.2017 / 09:26