Problemas ao executar o loop sobre uma série de comandos ssh-ed

1

Eu tenho uma série de máquinas servidoras nas quais quero executar o mesmo comando. Cada comando leva horas e (mesmo que eu esteja executando os comandos usando nohup e configurando-os para serem executados em segundo plano), tenho que esperar que cada um termine antes que o próximo inicie. Aqui está mais ou menos como eu configurei:

Nas máquinas host:

for i in {1..9}; do ssh RemoteMachine${i} ./RunJobs.sh; done

Onde RunJobs.sh em cada máquina remota é:

 source ~/.bash_profile
cd AriadneMatching
for file in FileDirectory/Input_*;
do
    nohup ./Executable ${file} &
done
exit

Alguém sabe de uma maneira tal que eu não tenho que esperar que cada trabalho termine antes das próximas partidas? Ou, alternativamente, uma maneira melhor de fazer isso, tenho a sensação de que o que eu faço é bastante insatisfatório. Felicidades, Jack

    
por JMzance 20.10.2013 / 23:35

4 respostas

0

Solução para a máquina local

Com base em parallel-ssh

# pssh -P --par 2 --hosts RemoteMachines /opt/RunJobs.sh

ou:

# pssh -i --par 2 --hosts RemoteMachines /opt/RunJobs.sh

Explicação dos parâmetros:

-P
--print
    Display output as it arrives.  This option is of limited usefulness
    because output from different hosts are interleaved.

-i
--inline
    Display standard output and standard error as each host completes.

-p parallelism
--par parallelism
    Use the given number as the maximum number of concurrent connections.

-h host_file
--hosts host_file
    Read hosts from the given host_file.

Com base em ansible

# ansible --forks 2 -i RemoteMachines '*' -m command -a /opt/RunJobs.sh

Explicação dos parâmetros:

-f NUM, --forks=NUM
    Level of parallelism.  NUM is specified as an integer, the default is 5.

-i PATH, --inventory=PATH
    The PATH to the inventory hosts file, which defaults to /etc/ansible/hosts.

-m NAME, --module-name=NAME
    Execute the module called NAME.

-a 'ARGUMENTS', --args='ARGUMENTS'
    The ARGUMENTS to pass to the module.

The command module takes the command name followed by a list of space-delimited arguments. The given command will be executed on all selected nodes. It will not be processed through the shell, so variables like $HOME and operations like "<", ">", "|", and "&" will not work.

Você pode ler mais na Introdução aos comandos ad-hoc .

N.B. ansible não irá mudar para o próximo grupo de hosts até que todos os hosts atuais ("forks") estejam prontos, então seu paralelismo é menor que pssh ( pode haver uma maneira de aumentá-lo, mas eu não sei).

O arquivo RemoteMachines se parece com isso nos dois casos:

[email protected]
[email protected]
[email protected]
[email protected]

Solução para as máquinas remotas

Reescreva RunJobs.sh em algo parecido com isto:

find FileDirectory -name 'Input_*' -print0 | xargs -0 -P 2 -n 1 ./Executable

Explicação :

-0, --null
       Input items are terminated by a null character instead of by
       whitespace, and the quotes and backslash are not special (every
       character is taken literally).  Disables the end of file string,
       which is treated like any other argument.  Useful when input items
       might contain white space, quote marks, or backslashes.  The GNU find
       -print0 option produces input suitable for this mode.

-P max-procs, --max-procs=max-procs
       Run  up to max-procs  processes at a time; the default is 1.  If
       max-procs is 0, xargs will run as many processes as possible at a
       time.  Use the -n option or the -L option with -P; otherwise chances
       are  that  only  one  exec will be done.

 -n max-args, --max-args=max-args
       Use at most max-args arguments per command line.  Fewer than
       max-args arguments will be used if the size (see the -s option) is
       exceeded, unless the -x option is given, in which case xargs will
       exit.

do nitro2k01 A solução baseada no GNU Parallel é mais poderosa, mas como você pode ver, o GNU xargs também não é muito ruim.

    
por 21.10.2013 / 05:10
2

Primeiramente, você pode querer usar screen em vez de nohup para fazer com que a sessão sobreviva a uma desconexão. screen fornece um terminal virtual para o qual você pode retornar mais tarde. O uso básico é screen yourcommand para executar yourcommand e screen -DR para se conectar automaticamente a uma sessão existente ou criar uma nova, se nenhuma existir. Apenas executar a tela sem um argumento também fornece um prompt dentro de uma "tela" que você pode usar.

Em segundo lugar, você pode querer olhar para GNU Parallel para trabalhos paralelos. Você pode não querer ter mais processos em execução do que os núcleos da CPU, devido a retornos decrescentes e sobrecarga de disco. Um comando adequado para você pode ser o seguinte, que, mais uma vez, você teria que executar dentro de uma tela para sobreviver à desconexão.

ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {}

Os arquivos que você deseja processar são listados e canalizados para parallel , que é instruído a executar 8 trabalhos paralelos e trabalhar no diretório atual.

Como a tela não entende os pipes e outras coisas nos comandos dados como um argumento - esse é o trabalho do shell - você precisaria colocar o comando no shell script ou dar um comando sh -c para executar o comando. / p>

screen sh -c 'ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {}'

ou simplesmente

screen ./runjob

onde runjob contém:

#!/usr/bin/env bash
ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {}
    
por 20.10.2013 / 23:59
1

Use tela em cada máquina. screen inicia um comando (geralmente um shell) que pode ser separado da sua sessão ssh, de modo que continue executando o job que acabou de ser iniciado dentro dele; Em outras palavras, o trabalho, embora ainda esteja em execução, não será interrompido por nenhuma interrupção (não apenas kill -9) à medida que você efetua logout.

Quando quiser, você pode se reconectar via ssh e voltar a participar da sessão desanexada através do comando

screen -r

e isso o colocará de volta no shell que você abandonou, mostrando a saída padrão que você perdeu nesse meio tempo, se houver.

Assim, você não tem que esperar por nada, nem você tem perigosamente pendurado sessões ssh que, se desconectadas acidentalmente, matariam seus trabalhos.

A tela

está nos repos.

    
por 20.10.2013 / 23:51
0

para i em {1..9}; do ssh RemoteMachine $ {i} ./RunJobs.sh; feito

tente isso

for i in {1..9}; do echo RemoteMachine${i}; done |xargs -I % -n 1 -P 10 ssh
% "./RunJobs.sh"

o que isso faz é construir uma lista de nomes de máquinas e canalizar toda a lista para xargs. Os argumentos para xargs significam:

-I% substitui a ocorrência de% pelo primeiro argumento

-n 1 usa 1 argumento por linha de comando

-P 10 executa 10 processos de cada vez

    
por 25.10.2013 / 14:49