Kontekst:
Użytkownicy udostępniają mi swoje niestandardowe skrypty do uruchomienia. Skrypty te mogą być wszelkiego rodzaju jak skrypty do uruchamiania wielu programów GUI, usług zaplecza. Nie mam kontroli nad sposobem pisania skryptów. Skrypty te mogą być typu blokującego, tzn. Wykonywanie czeka do momentu zakończenia wszystkich procesów potomnych (programów uruchamianych sekwencyjnie)
#exaple of blocking script
echo "START"
first_program
second_program
echo "DONE"
lub typu nieblokującego, tzn. takie, które rozwidlają proces potomny w tle i zamykają coś podobnego
#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"
Co próbuję osiągnąć?
Skrypty dostarczone przez użytkownika mogą należeć do dowolnego z powyższych dwóch typów lub być kombinacją obu. Moim zadaniem jest uruchomienie skryptu i poczekanie, aż wszystkie procesy rozpoczęte przez niego zakończą się, a następnie zamkną węzeł. Jeśli jest typu blokującego, wielkość liter jest po prostu prosta, tzn. Uzyskaj PID procesu wykonywania skryptu i poczekaj, aż ps -ef | grep -ef PID nie będzie już zawierał żadnych wpisów. Skrypty nieblokujące powodują problemy
Czy istnieje sposób, aby uzyskać listę PID wszystkich procesów potomnych odradzanych przez wykonanie skryptu? Wszelkie wskazówki lub wskazówki będą mile widziane
pid$(foo.sh; echo $!)
co da ci PIDfoo.sh
, abyś mógł z niego skorzystaćps --ppid
. Czy to będzie działało?grep
, po prostups –udummy_user
. Zobacz także grupy procesów.ps
bez żadnych argumentów (powinno być tylkobash
ips
na początku). Rozpocznij swój skrypt tam. Po zakończeniu poczekaj, ażps | wc -l
osiągnie oczekiwaną wartość.Odpowiedzi:
Aby bezpośrednio odpowiedzieć na twoje pytanie, polecenie
daje listę wszystkich procesów potomnych.
Alternatywa nr 1
Ale w twoim przypadku może być łatwiej po prostu użyć polecenia
wait
bez żadnych parametrów:Będzie to czekało na zakończenie WSZYSTKICH procesów potomnych.
Alternatywa # 2
Inną alternatywą jest użycie,
$!
aby uzyskać PID ostatniego programu i być może skumulować w zmiennej, tak jak:a następnie użyj z tym czekania (w przypadku, gdy chcesz tylko czekać na podzbiór procesów potomnych):
Alternatywa nr 3
LUB, jeśli chcesz czekać tylko na zakończenie ŻADNEGO procesu, możesz użyć
Informacje o bonusie
Jeśli chcesz, aby sigterm w skrypcie bash również zamykał procesy potomne, musisz propagować sygnał za pomocą czegoś takiego (umieść to gdzieś u góry, przed rozpoczęciem jakiegokolwiek procesu):
źródło
Dzięki chłopaki za odpowiedzi. Mam rozwiązanie w sprawie stackoverflow
Możesz użyć funkcji wait, aby poczekać na zakończenie wszystkich procesów uruchomionych przez skrypt użytkownika w tle. Ponieważ czekanie działa tylko na elementach potomnych bieżącej powłoki, będziesz musiał pobrać ich skrypt zamiast uruchamiać go jako osobny proces.
(źródłowy skrypt użytkownika; czekaj)
Pozyskanie skryptu w jawnej podpowłoce powinno wystarczająco dokładnie symulować rozpoczęcie nowego procesu. Jeśli nie, możesz także utworzyć podkładkę w tle, co wymusza uruchomienie nowego procesu, a następnie poczekaj na jego zakończenie.
(źródłowy skrypt użytkownika; czekaj) i czekaj
Oto link do oryginalnej odpowiedzi @chepner: /programming/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18663969
źródło
wait
polecenie będzie wtedy czekać na dzieci skryptu użytkownika, ale nie na jego wnuki.