Aguarde a conclusão dos processos em segundo plano com o ID do processo de correspondência inversa

4

Estou procurando executar vários processos em segundo plano em um loop, mas só quero esperar que todos esses processos sejam concluídos, permitindo ainda que outro processo em segundo plano continue.

Depois de fazer uma pesquisa, vejo apenas soluções que exigem que eu liste todos os IDs de processo para os quais desejo wait , em vez de compará-los inversamente com um único ID de processo. Parece que algo como wait != $pid seria muito útil.

script de exemplo:

#!/bin/bash

command1 &
pid=$!
for i in ${array[@]}; do
    for n in $(seq 3); do
        if [ $n -eq 1 ];
            command2 > file &
        else
            command2 >> file &
        fi
    done
done

Neste exemplo, espero que todos os processos sejam concluídos, exceto $pid , sem precisar listá-los usando o comando wait . Isso é possível?

    
por John B 09.09.2013 / 01:54

2 respostas

3

Como outros já disseram, não há como esperar "não" um ID de processo. No entanto, esse padrão de código não parece tão ruim para mim, então ofereço isso como uma maneira sugerida de conseguir o que você procura.

Ele faz uso de matrizes Bash, que você pode fornecer como uma lista para o comando wait .

Exemplo

Uma versão modificada do seu código de exemplo, cmd.bash .

!/bin/bash

array[0]=1
array[0]=2

sleep 30 &
pid=$!

pidArr=()
for i in ${array[@]}; do
  for n in $(seq 3); do
    if [ $n -eq 1 ]; then
      sleep 31 > file &
      pidArr+=($!)
    else
      sleep 32 >> file &
      pidArr+=($!)
    fi
  done
done

echo ${pidArr[@]}

Eu substituí os comandos sleep neste exemplo apenas para simular alguns trabalhos longos que podemos usar em segundo plano. Eles não têm nada a ver com isso além de agir como substitutos.

O comando final echo também está disponível para que possamos ver o que acontece quando os loops for completos. Por fim, vamos substituí-lo por um comando wait real, mas não vamos nos antecipar.

Exemplo de corrida nº 1

Então, vamos executar nosso programa e ver o que acontece.

$ ./cmd.bash 
24666 24667 24668

Agora, se verificarmos ps :

$ ps -eaf|grep sleep
saml     24664     1  0 22:28 pts/9    00:00:00 sleep 30
saml     24666     1  0 22:28 pts/9    00:00:00 sleep 31
saml     24667     1  0 22:28 pts/9    00:00:00 sleep 32
saml     24668     1  0 22:28 pts/9    00:00:00 sleep 32

Se esperarmos um pouco, estes acabarão por terminar. Mas isso mostra que, se adicionarmos os IDs do processo a um array, poderemos echo -los depois.

Exemplo # 2

Então, vamos alterar esse echo line out e trocar em uma linha wait agora, algo assim:

  wait ${pidArr[@]}

Agora, quando executamos nossa versão modificada, vemos que ela está aguardando TODOS os IDs do processo:

$ ./cmd.bash 

... após ~ 30 segundos passa

$

Voltamos ao nosso aviso. Então, esperamos com sucesso por todos os processos. Uma rápida verificação de ps :

$ ps -eaf|grep sleep
$

Então funcionou.

    
por 09.09.2013 / 04:34
6

O que há de errado com apenas

wait

Como help wait notas:

Waits for the process identified by ID, which may be a process ID or a job specification, and reports its termination status. If ID is not given, waits for all currently active child processes, and the return status is zero.

Você deseja "ainda permitir que outro processo em segundo plano continue"? Apenas disown . Seguindo seu exemplo:

command1 & disown %1
command2 & command2 & command2 &
wait
    
por 09.09.2013 / 02:17

Tags