Mam skrypt, który chciałbym w pewnym momencie rozwidlić, więc działają dwie kopie tego samego skryptu.
Na przykład , Chciałbym, aby istniał następujący skrypt bash:
echo $$ do_fork() echo $$
Gdyby ten skrypt bash naprawdę istniał, oczekiwanym wynikiem byłoby:
<ProcessA PID> <ProcessB PID> <ProcessA PID>
lub
<ProcessA PID> <ProcessA PID> <ProcessB PID>
Czy jest coś, co mogę wstawić zamiast „do_fork ()”, aby to uzyskać rodzaj wyjścia czy spowodować, że skrypt bash wykona rozwidlenie w stylu C?
Odpowiedź
Tak. Rozwidlanie jest zapisywane jako &
:
echo child & echo parent
Może być mylące, że $$
nie jest PID procesu powłoki, to jest PID oryginalnego procesu powłoki. Celem zrobienia tego w ten sposób jest to, że $$
jest unikalnym identyfikatorem dla konkretnej instancji skryptu powłoki: nie zmienia się podczas wykonywania skryptu i różni się od $$
w każdym innym równolegle działającym scenariusz. Jednym ze sposobów uzyskania rzeczywistego PID procesu powłoki jest sh -c "echo $PPID"
.
Przepływ sterowania w powłoce nie jest taki sam jak w C. Jeśli w C „d pisz
first(); fork(); second(); third();
to odpowiednikiem powłoki jest
after_fork () { second; third; } first; after_fork & after_fork
Prosta forma powłoki first; child & parent
odpowiada zwykłemu idiomowi w C
first(); if (fork()) parent(); else child();
&
i $$
istnieją i zachowują się w ten sposób w każdej powłoce w stylu Bournea oraz w (t) csh. $PPID
nie istniało w oryginalnej wersji Bournea shell, ale jest w POSIX (więc jest w ash, bash, ksh, zsh,…).
Komentarze
Odpowiedź
Tak, nazywa się to podpowłokami . Kod powłoki w nawiasach jest uruchamiany jako podpowłoka (rozwidlenie). Jednak pierwsza powłoka zwykle czeka na zakończenie działania elementu podrzędnego. Możesz ustawić ją jako asynchroniczną za pomocą terminatora &
. Zobacz to w akcji za pomocą czegoś takiego:
#!/bin/bash (sleep 2; echo "subsh 1")& echo "topsh"
$ bash subsh.sh
Komentarze
- Nawiasy tworzą podpowłokę , ale to ' s fork + wait.
&
to samo rozwidlenie. Jeśli chcesz wykonać więcej niż jeden potok w procesie potomnym, wystarczy ', aby użyć nawiasów klamrowych (które wykonują grupowanie bez tworzenia procesu potomnego):{ sleep 2; echo child; } &
Odpowiedź
Nie ma natywnej bash (lub, o ile wiem, jakikolwiek inny typowy sposób powłoki * nix). Istnieje wiele sposobów tworzenia rozwidlonych procesów, które wykonują coś innego asynchronicznie, ale nie sądzę, aby było coś, co byłoby zgodne z dokładną semantyką wywołania systemowego fork ().
Typowe podejście niech twój skrypt najwyższego poziomu wyłączy pomocników, którzy wykonują tylko to, co chcesz, aby się rozdzieliły. Jeśli zrobisz $0 $@ &
lub cokolwiek innego, zaczniesz od początku od nowa i musisz jakoś to rozgryźć.
Właściwie zaczynam wymyślać kilka sprytnych sposobów, w jakie można by to zrobić ….
Ale , zanim mój mózg zbytnio się tym przejmie, myślę, że całkiem dobra zasada brzmi: jeśli próbujesz napisać coś w powłoce, pełen sprytnych sztuczek i „chcesz mieć więcej funkcji językowych, czasu na przejście na prawdziwy język programowania .
Komentarze
- Chociaż twój punkt widzenia jest dobrze zrozumiany – składnia bash ' jest prawdopodobnie trudna i ' Brak bardziej eleganckich struktur danych i funkcji Perla lub Pythona, bash jest tak realny, jak to tylko możliwe – w swojej domenie . Jest to język specyficzny dla domeny i argumentowałbym nawet lepiej (bardziej zwięźle, prościej) niż np. Python w wielu przypadkach. Czy potrafisz administrować pomieszczeniem pełnym systemów i nie znasz języka Python? Tak. Potrafisz to zrobić i nie znać się na bash [programowaniu]? Nie ' nie chciałbym próbować. Po 30 latach programowania powłoki mówię, że ' jest tak realne, jak to tylko możliwe. I tak, mówię w Pythonie. Ale nie ' nie myl dzieci.
- To powiedziawszy, technicznie rzecz biorąc, bardziej podoba mi się ta odpowiedź. Stwierdzenie, że " & " jest odpowiedzią dla użytkownika ' s pytanie, " rozwidla się w jednym miejscu, tak że działają dwie kopie tego samego skryptu " mylący umysł. Zgodnie z instrukcją basha " & " to " … wykonuje [podane] polecenie w tle w podpowłoce. " Musi zakończyć polecenie i wymaga rozwidlenia (technicznie , w Linuksie clone ()), ale w tym momencie nie działają dwie kopie tego samego skryptu.
&
to fork, tam ' nie jest zaangażowany w exec. Fork + exec jest uruchamiany po uruchomieniu polecenia zewnętrznego.exec
, ale te dwa języki mają inny przepływ sterowania.&
uruchamia podpowłokę, w której wykonywane jest dane polecenie. Fork + exec. Możesz ' po prostu wstawić&
bez poprzedzającego polecenia do wykonania.&
w osobnej linii. Ale możesz ' t. Nie ' nie oznacza " rozwidlenia tutaj ". Oznacza to " wykonanie poprzedniego polecenia w tle w podpowłoce ".