Сценарий оболочки ожидает фоновую команду

12

Я пишу сценарий, но мне нужно кое-что, что я не могу найти способ сделать это ...

Мне нужно сделать команду в фоновом режиме «command1 &», а затем где-нибудь в скрипте мне нужно дождаться ее завершения, прежде чем я выполню command2. В принципе, мне нужно это:

ПРИМЕЧАНИЕ: каждая команда выполняется в определенном каталоге! в конце цикла while моя команда 1 создала 4 каталога, где в каждом из них выполнялся определенный процесс, поэтому общее количество запущенных процессов равно 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

Я видел кое-что о waitкоманде с номером процесса pid, но это тоже не сработало.

Жоао Макао
источник
Вы контролируете command1? Можете ли вы изменить его так, чтобы он возвращал PID 4 процессов?
Terdon
Да! у меня это уже есть :)
Жоао Макао
Я обновил свой ответ соответственно. Скажи мне, если это соответствует твоим ожиданиям.
Лоран С.
Этот вопрос связан с этим: unix.stackexchange.com/questions/100801/… . Единственное отличие заключается в том, что вам нужно получить PID от фонового процесса. Вы можете использовать $!переменную, чтобы получить это, передав ее waitкоманде, как я там показал. $!содержит последний фоновый PID, а PID $$последнего запуска процесса.
SLM
3
Хорошо, теперь ваш сценарий не имеет никакого смысла. Вокруг синтаксические ошибки и странности. Не могли бы вы показать нам реальный сценарий? Почему вы используете команды? Почему бы просто не выполнить их?
Terdon

Ответы:

22

Вы можете использовать команду wait PIDдля ожидания завершения процесса.

Вы также можете получить PID последней команды с помощью $!

В вашем случае что-то вроде этого будет работать:

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

После вашего редактирования, поскольку у вас есть несколько идентификаторов PID и вы их знаете, вы можете сделать это:

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
Лоран К.
источник
После вашего редактирования, если вы знаете, что создан PID (xxxxx, yyyyy, xxyyy, yyxxx), вы также можете использовать wait со списком PID для ожидания (см. Man). Если вы их не знаете, может быть, вы сможете собрать их в команду 1 (что такое команда 1? Ваш собственный сценарий?)
Лоран С.
Вероятно, лучше всего убедиться, что они правильно сгруппированы. Смотрите мой ответ, чтобы понять, как это можно сделать.
mikeserv
4

Самый простой способ сделать это - comamnd1вернуть PID запущенных процессов и использовать их waitдля каждого из них, как указано в ответе @ LaurentC .

Другой подход будет примерно таким:

## 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
Тердон
источник
извините, но все еще не работает .. Я еще раз улучшу свой вопрос!
Жоао Макао
0

Если вы используете следующий метод, вам может не потребоваться специальное «ожидание всех процессов» после цикла while. Цикл будет ждать завершения тока, command1прежде чем он вернется к началу. Пожалуйста, будьте осторожны, как с любым советом. Обратите внимание, единственное, что я сделал, это добавил & wait $!в конец твоего command1.

a=1
while [$a -lt 4 ]
     . command1  & wait $!
   #Generates 1 Process  
     a= `export $a +1`
done
Мариус М
источник