Skrypt powłoki oczekuje na polecenie w tle

12

Piszę scenariusz, ale jest coś, czego potrzebuję, że nie mogę znaleźć sposobu, aby to zrobić ...

Muszę wykonać polecenie w tle „polecenie1 i”, a następnie gdzieś w skrypcie muszę poczekać, aż zakończy się, zanim wykonam polecenie2. Zasadniczo potrzebuję tego:

UWAGA: każde polecenie działa w określonym katalogu! na końcu pętli while moje polecenie1 utworzyło 4 katalogi, w których w każdym uruchamiany jest określony proces, więc całkowita liczba uruchomionych procesów wynosi 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

Widziałem coś o waitpoleceniu z numerem procesu pid, ale to też nie działało.

Joao Macau
źródło
Czy ty kontrolujesz command1? Czy możesz go zmodyfikować, aby zwracał PID 4 procesów?
terdon
Tak! już to mam :)
Joao Macau
Zaktualizowałem odpowiednio swoją odpowiedź. Powiedz mi, czy pasuje to do twoich oczekiwań.
Laurent C.
To pytanie jest powiązane z tym: unix.stackexchange.com/questions/100801/… . Jedyną różnicą jest to, że musisz uzyskać PID z procesu działającego w tle. Możesz użyć tej $!zmiennej, aby to uzyskać, przekazując ją do waitpolecenia, jak tam pokazałem. $!zawiera PID ostatniego tła, podczas gdy $$zawiera PID ostatniego przebiegu procesu.
slm
3
OK, teraz twój skrypt w ogóle nie ma sensu. Wokół występują błędy składniowe i dziwność. Czy możesz nam pokazać rzeczywisty skrypt? Dlaczego pozyskujesz polecenia? Dlaczego po prostu ich nie wykonać?
terdon

Odpowiedzi:

22

Możesz użyć polecenia, wait PIDaby poczekać na zakończenie procesu.

Możesz także pobrać PID ostatniego polecenia za pomocą $!

W twoim przypadku coś takiego działałoby:

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

Po zakończeniu edycji, ponieważ masz wiele identyfikatorów PID i znasz je, możesz to zrobić:

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.
źródło
Po zakończeniu edycji, jeśli znasz utworzony PID (xxxxx, rrrr, xxyyy, yyxxx), możesz również użyć funkcji czekania, z listą PIDów, na które trzeba czekać (patrz man). Jeśli ich nie znasz, może uda ci się zebrać je w polecenie 1 (co to jest polecenie 1? Własny skrypt?)
Laurent C.
Najprawdopodobniej najlepiej, aby upewnić się, że są poprawnie zgrupowane. Zobacz moją odpowiedź, aby dowiedzieć się, jak to zrobić.
mikeserv
4

Najczystszym sposobem na to będzie mieć swój comamnd1zwróci PID uruchomionych procesów i przy użyciu waitkażdego z nich jak sugeruje @ LaurentC za odpowiedź .

Innym podejściem byłoby coś takiego:

## 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
źródło
przepraszam ale nadal nie działa .. Poprawię moje pytanie jeszcze raz!
Joao Macau
0

Jeśli zastosujesz następującą metodę, możesz nie potrzebować specjalnego „czekania na wszystkie procesy” po pętli while. Pętla zaczeka na zakończenie prądu, command1zanim przejdzie do następnego cyklu. Proszę zachować ostrożność jak w przypadku każdej porady. Zauważ, że jedyną rzeczą, którą zrobiłem, było dodanie & wait $!do końca twojego command1.

a=1
while [$a -lt 4 ]
     . command1  & wait $!
   #Generates 1 Process  
     a= `export $a +1`
done
Marius M.
źródło