Digamos que tenhamos um script bash assim:
echo "x" &
echo "y" &
echo "z" &
.....
echo "Z" &
wait
existe uma maneira de coletar os códigos de saída dos subcascas / subprocessos? Procurando uma maneira de fazer isso e não consegue encontrar nada. Eu preciso executar esses subshells em paralelo, caso contrário, isso seria mais fácil.
Estou procurando uma solução genérica (tenho um número desconhecido / dinâmico de subprocessos para executar em paralelo).
bash
shell-script
shell
subshell
Alexander Mills
fonte
fonte
Respostas:
A resposta de Alexander Mills, que usa handleJobs, me deu um ótimo ponto de partida, mas também me deu esse erro
O que pode ser um problema básico de condição de corrida
Em vez disso, apenas armazenei o pid de cada criança e esperei e obtive o código de saída para cada criança especificamente. Acho esse limpador em termos de subprocessos gerando subprocessos em funções e evitando o risco de esperar por um processo pai no qual pretendia esperar pelo filho. É mais claro o que acontece porque não está usando a armadilha.
fonte
for job in "${childen[@]}"; do
deve serfor job in "${1}"; do
, porém, para maior clarezachildren_pids+=("$!")
realmente está capturando o pid desejado para o sub shell.Use
wait
com um PID, que irá:Você precisará salvar o PID de cada processo à medida que avança:
Você também pode ativar o controle de tarefas no script
set -m
e usar uma%n
especificação de tarefas, mas quase certamente não deseja - o controle de tarefas tem muitos outros efeitos colaterais .wait
retornará o mesmo código que o processo finalizado. Você pode usarwait $X
a qualquer momento (razoável) posteriormente para acessar o código final$?
ou simplesmente usá-lo como verdadeiro / falso:wait
fará uma pausa até que o comando seja concluído, se ainda não o tiver feito.Se você quiser evitar parar assim, você pode definir um
trap
emSIGCHLD
, contar o número de terminações, e lidar com todos oswait
s de uma só vez quando temos tudo acabado. Você provavelmente pode usar o usowait
sozinho quase o tempo todo.fonte
wait $X
em qualquer ponto posterior (razoável).Se você tiver uma boa maneira de identificar os comandos, poderá imprimir o código de saída em um arquivo tmp e acessar o arquivo específico em que está interessado:
Não se esqueça de remover os arquivos tmp.
fonte
Use a
compound command
- coloque a declaração entre parênteses:dará a saída
Uma maneira realmente diferente de executar vários comandos em paralelo é usando o GNU Parallel . Faça uma lista de comandos para executar e coloque-os no arquivo
list
:Execute todos os comandos em paralelo e colete os códigos de saída no arquivo
job.log
:e a saída é:
fonte
PIPESTATUS
seja algo que você deva conferir. Issoseq 10 | gzip -c > seq.gz ; echo ${PIPESTATUS[@]}
retorna0 0
(código de saída do primeiro e do último comando).esse é o script genérico que você está procurando. A única desvantagem é que seus comandos estão entre aspas, o que significa que o destaque da sintaxe via IDE não funcionará realmente. Caso contrário, tentei algumas das outras respostas e essa é a melhor. Esta resposta incorpora a idéia de usar
wait <pid>
dada por @Michael, mas vai um passo além usando otrap
comando que parece funcionar melhor.obrigado a @michael homer por me colocar no caminho certo, mas usar o
trap
comando é a melhor abordagem para o AFAICT.fonte
Outra variação da resposta de @rolf:
Outra maneira de salvar o status de saída seria algo como
e depois tem cada script
Isso fornece um nome exclusivo para cada arquivo de status, incluindo o nome do script que o criou e seu ID do processo (caso mais de uma instância do mesmo script esteja em execução), que você pode salvar para referência posteriormente e colocá-los todos no diretório no mesmo local para excluir o subdiretório inteiro quando terminar.
Você pode até salvar mais de um status de cada script fazendo algo como
que cria o arquivo como antes, mas adiciona uma sequência aleatória exclusiva a ele.
Ou você pode simplesmente acrescentar mais informações de status ao mesmo arquivo.
fonte
script3
será executado somente sescript1
escript2
são bem sucedidos escript1
escript2
será executado em paralelo:fonte