for((i=1;i<100;i++)); do nohup bash script${i}.sh & done
Suponha que eu tenha três (ou mais) scripts do bash: script1.sh
, script2.sh
e script3.sh
. Eu gostaria de chamar todos esses três scripts e executá-los em paralelo . Uma maneira de fazer isso é apenas executar os seguintes comandos:
nohup bash script1.sh &
nohup bash script2.sh &
nohup bash script3.sh &
(Em geral, os scripts podem demorar várias horas ou dias para serem concluídos, portanto, eu gostaria de usar nohup
para que eles continuem sendo executados mesmo se meu console for fechado.)
Mas, existe alguma maneira de executar esses três comandos em paralelo com uma chamada única ?
Eu estava pensando em algo como
nohup bash script{1..3}.sh &
mas isso parece executar script1.sh
, script2.sh
e script3.sh
na sequência, não em paralelo.
A melhor maneira seria usar GNU Parallel . O GNU paralelo é simples e, com ele, podemos controlar o número de tarefas a serem executadas em paralelo com mais controle sobre as tarefas.
No comando abaixo, script{1..3}.sh
é expandido e enviado como argumentos para bash
em paralelo. Aqui -j0
indica que tantos trabalhos devem ser executados quanto possível. Por padrão, parallel
executa um trabalho para um núcleo de CPU.
$ parallel -j0 bash :::: <(ls script{1..3}.sh)
E você também pode tentar usar
$ parallel -j0 bash ::: script{1..3}.sh
Ao executar o segundo método, se você receber alguma mensagem de erro, significa que a opção --tollef
está definida em /etc/parallel/config
e que precisa ser excluída e tudo funcionará bem.
Você pode ler a página de manual GNU Parallels
aqui para obter opções mais ricas.
E caso você esteja executando os trabalhos de uma máquina remota, use melhor screen
para que a sessão não é fechada devido a problemas de rede. nohup
não é necessário, já que as versões recentes do bash vêm com huponexit
as off
e isso impedirá que o shell pai envie o sinal HUP
para seus filhos durante sua saída. No caso, se não é inset não fazê-lo com
$ shopt -u huponexit
Também podemos usar xargs
para executar vários scripts em paralelo.
$ ls script{1..5}.sh|xargs -n 1 -P 0 bash
aqui cada script é passado para bash como argumento separadamente. -P 0
indica que o número de processos paralelos pode ser o máximo possível. Também é mais seguro usar o padrão bash job control feature
(&)
.
Uma única solução line :
$ nohup bash script1.sh & nohup bash script2.sh & nohup bash script3.sh &
Menos facetiously, basta usar um script de wrapper:
$ cat script.sh
#!/usr/bin/env bash
script1.sh &
script2.sh &
script3.sh &
$ nohup script.sh &
Ou passe por cima deles:
for script in dir/*.sh
do
nohup bash "$script" &
done
Se você quer economizar um pouco de esforço de digitação
eval "nohup bash "script{1..3}.sh" &"
Ou pensando duas vezes, talvez não
Faça o check-out desta ferramenta: link
Digamos que você tenha mytasks.yaml
com
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 você executa assim:
nohup bashful run mytasks.yaml
Seus scripts seriam executados em paralelo com uma barra de progresso vertical (+ eta se você executou antes e o tempo é determinístico). Você pode ajustar quantas tarefas deseja executar em paralelo, se você começar a executar mais do que apenas o dado 3 aqui:
config:
max-parallel-commands: 6
tasks:
...
Aviso: eu sou o autor.
Estou sugerindo um utilitário muito mais simples que acabei de escrever. É atualmente chamado de par, mas será renomeado em breve para parl ou pll, ainda não foi decidido.
A API é tão simples quanto:
par "script1.sh" "script2.sh" "script3.sh"