Powiedzmy, że mamy taki skrypt bashowy:
echo "x" &
echo "y" &
echo "z" &
.....
echo "Z" &
wait
czy istnieje sposób na zebranie kodów wyjścia z podpowłok / podprocesów? Szukasz sposobu na zrobienie tego i nic nie możesz znaleźć. Muszę uruchomić te podpowłoki równolegle, w przeciwnym razie tak byłoby łatwiej.
Szukam ogólnego rozwiązania (mam nieznaną / dynamiczną liczbę podprocesów do równoległego działania).
bash
shell-script
shell
subshell
Alexander Mills
źródło
źródło
Odpowiedzi:
Odpowiedź Alexandra Millsa, która używa handleJobs, dała mi świetny punkt wyjścia, ale także dała mi ten błąd
Co może być problemem wyścigu bash
Zamiast tego po prostu zapisałem pid każdego dziecka i czekam, a konkretnie dostaje kod wyjścia dla każdego dziecka. Uważam to za czystsze, jeśli chodzi o podprocesy spawnujące podprocesy w funkcjach i unikające ryzyka oczekiwania na proces nadrzędny, w którym chciałem czekać na dziecko. Wyraźniejsze jest to, co się dzieje, ponieważ nie używa pułapki.
źródło
for job in "${childen[@]}"; do
powinno byćfor job in "${1}"; do
, dla jasnościchildren_pids+=("$!")
faktycznie przechwytuje pożądany pid dla podpowłoki.Używaj
wait
z PID, który :Musisz zapisać PID każdego procesu na bieżąco:
Możesz także włączyć kontrolę zadań w skrypcie
set -m
i używać%n
specyfikacji zadań, ale prawie na pewno nie chcesz - kontrola zadań ma wiele innych skutków ubocznych .wait
zwróci ten sam kod, co zakończony proces. Możesz użyćwait $X
w dowolnym (rozsądnym) momencie, aby uzyskać dostęp do końcowego kodu jako$?
lub po prostu użyć go jako true / false:wait
zatrzyma się, aż polecenie zakończy się, jeśli jeszcze tego nie zrobiło.Jeśli chcesz uniknąć przeciągnięcia tak, można ustawić
trap
naSIGCHLD
, policzyć liczbę zakończeń i obsługiwać wszystkiewait
s od razu, kiedy już wszystko jest gotowe. Prawdopodobnie możesz przezwait
cały czas uniknąć samodzielnego używania .źródło
wait $X
w dowolnym (rozsądnym) momencie.Jeśli masz dobry sposób na identyfikację poleceń, możesz wydrukować ich kod wyjścia do pliku tmp, a następnie uzyskać dostęp do określonego pliku, który Cię interesuje:
Nie zapomnij usunąć plików tmp.
źródło
Użyj a
compound command
- umieść instrukcję w nawiasach:da wynik
Zupełnie innym sposobem równoległego uruchamiania kilku poleceń jest użycie GNU Parallel . Zrób listę poleceń do uruchomienia i umieść je w pliku
list
:Uruchom wszystkie polecenia równolegle i zbierz kody wyjścia w pliku
job.log
:a wynikiem jest:
źródło
PIPESTATUS
warto to sprawdzić. Teseq 10 | gzip -c > seq.gz ; echo ${PIPESTATUS[@]}
powroty0 0
(kod wyjścia z polecenia pierwszego i ostatniego).to jest ogólny skrypt, którego szukasz. Jedynym minusem jest to, że twoje polecenia są w cudzysłowach, co oznacza, że podświetlanie składni za pomocą IDE nie będzie naprawdę działać. W przeciwnym razie wypróbowałem kilka innych odpowiedzi i ta jest najlepsza. Ta odpowiedź zawiera pomysł użycia
wait <pid>
podany przez @Michaela, ale idzie o krok dalej, używająctrap
polecenia, które wydaje się działać najlepiej.dzięki @michael homer za doprowadzenie mnie na właściwą ścieżkę, ale użycie
trap
polecenia jest najlepszym podejściem AFAICT.źródło
Kolejna odmiana odpowiedzi @rolf:
Innym sposobem na zapisanie statusu wyjścia byłoby coś takiego
a następnie mieć każdy skrypt
Daje to unikalną nazwę dla każdego pliku statusu, w tym nazwę skryptu, który go utworzył, i jego identyfikator procesu (w przypadku, gdy uruchomiona jest więcej niż jedna instancja tego samego skryptu), którą można zapisać do późniejszego wykorzystania i umieścić je w to samo miejsce, więc możesz po prostu usunąć cały podkatalog po zakończeniu.
Możesz nawet zapisać więcej niż jeden status z każdego skryptu, robiąc coś takiego
który tworzy plik jak poprzednio, ale dodaje do niego unikatowy ciąg losowy.
Lub możesz po prostu dołączyć więcej informacji o stanie do tego samego pliku.
źródło
script3
zostanie wykonany tylko wtedy, gdyscript1
iscript2
są skuteczne iscript1
iscript2
będą realizowane równolegle:źródło