Script shell esperar pelo comando em segundo plano

12

Estou escrevendo um script, mas há algo de que preciso que não consigo encontrar uma maneira de fazê-lo ...

Preciso fazer um comando em segundo plano "command1 &" e, em algum lugar do script, preciso esperar que ele termine antes de executar o command2. Basicamente, eu preciso disso:

NOTA: cada comando é executado em um diretório específico! no final do loop while, meu command1 criou 4 diretórios, nos quais cada um executa o processo específico, de modo que o total de processos em execução é 4

a=1

while [$a -lt 4 ]

     . command1
   #Generates 1 Process  

     a= `export $a +1`
done

   #Wait until the 4 process end and then run the command2 

    . command2

Eu vi algo sobre um waitcomando com o número do processo pid, mas isso não funcionou também.

João Macau
fonte
Você controla command1? Você pode modificá-lo para que ele retorne os PIDs dos 4 processos?
terdon
Sim! eu tenho que já :)
João Macau
Atualizei minha resposta de acordo. Diga-me se corresponde às suas expectativas.
Laurent C.
Este Q está relacionado a este: unix.stackexchange.com/questions/100801/… . A única diferença é que você precisa obter o PID de um processo em segundo plano. Você pode usar a $!variável para obter isso, passando-a para o waitcomando como mostrei lá. $!contém o último PID em segundo plano, enquanto $$contém o último PID da execução do processo.
Slm
3
OK, agora seu script não faz nenhum sentido. Existem erros de sintaxe e estranheza por toda parte. Você poderia nos mostrar o script real ? Por que você está adquirindo comandos? Por que não apenas executá-los?
terdon

Respostas:

22

Você pode usar o comando wait PIDpara aguardar o término de um processo.

Você também pode recuperar o PID do último comando com $!

No seu caso, algo como isso funcionaria:

command1 & #run command1 in background
PID=$! #catch the last PID, here from command1
command2 #run command2 while command1 is running in background
wait $PID #wait for command1, in background, to end
command3 #execute once command1 ended

Após a sua edição, como você possui vários PIDs e os conhece, você pode fazer isso:

command1 & #run command1 in background
PID1=xxxxx
PID2=yyyyy
PID3=xxyyy
PID4=yyxxx
command2 #run command2 while command1 is running in background
wait $PID1 $PID2 $PID3 $PID4 #wait for the four processes of command1, in background, to end
command3 #execute once command1 ended
Laurent C.
fonte
Após a sua edição, se você souber o PID criado (xxxxx, aaaa, xxyyy, yyxxx), também poderá usar a espera, com a lista de PIDs a aguardar (consulte man). Se você d'ont conhecê-los, talvez você pode reunir-los em command1 (o que é command1 um roteiro de seu próprio?)
Laurent C.
Provavelmente, é melhor garantir que eles estejam agrupados corretamente em primeiro lugar. Veja minha resposta para ter uma idéia de como isso pode ser feito.
mikeserv
4

A maneira mais limpa de fazer isso seria comamnd1devolver os PIDs dos processos lançados e usá wait-los em cada um deles, conforme sugerido pela resposta da @ LaurentC .

Outra abordagem seria algo como isto:

## Create a log file
logfile=$(mktemp)

## Run your command and have it print into the log file
## when it's finsihed.
command1 && echo 1 > $logfile &

## Wait for it. The [ ! -s $logfile ] is true while the file is 
## empty. The -s means "check that the file is NOT empty" so ! -s
## means the opposite, check that the file IS empty. So, since
## the command above will print into the file as soon as it's finished
## this loop will run as long as  the previous command si runnning.
while [ ! -s $logfile ]; do sleep 1; done

## continue
command2
terdon
fonte
desculpe, mas ainda não está funcionando .. vou melhorar minha pergunta mais uma vez!
João Macau
0

Se você usar o método a seguir, poderá não precisar de uma "espera para todos os processos" especial após o loop while. O loop aguardará command1a conclusão da corrente antes de voltar ao topo. Por favor, tenha cuidado como em qualquer conselho. Observe que a única coisa que fiz foi adicionar & wait $!ao final do seu command1.

a=1
while [$a -lt 4 ]
     . command1  & wait $!
   #Generates 1 Process  
     a= `export $a +1`
done
Marius M
fonte