Trudno mi precyzyjnie sformułować pytanie, ale dam z siebie wszystko. Używam dwm
jako domyślnego menedżera okien idmenu
jako mój program uruchamiający aplikacje. Prawie nie używam aplikacji GUI poza przeglądarką. Większość mojej pracy jest wykonywana bezpośrednio z wiersza poleceń. Ponadto jestem wielkim fanem minimalizmu w odniesieniu do systemów operacyjnych, aplikacji itp. Jednym z narzędzi, którego nigdy się nie pozbyłem, było uruchamianie aplikacji. Głównie dlatego, że brakuje mi dokładnego zrozumienia działania programów uruchamiających aplikacje / ich działania. Nawet obszerne wyszukiwanie w Internecie pokazuje tylko niejasne wyjaśnienia. To, co chcę zrobić, to pozbyć się nawet mojego programu uruchamiającego aplikacje, ponieważ poza faktycznym spawaniem aplikacji, nie mam z niej absolutnie żadnego pożytku. W tym celu naprawdę chciałbym wiedzieć, jak „poprawnie” uruchamiać aplikacje z powłoki. Przy czym znaczenie „poprawnie” może być przybliżone przez „tak jak zrobiłby to program uruchamiający aplikacje”.
Wiem o następujących sposobach odradzania procesów z powłoki:
exec /path/to/Program
zamień powłokę na określone polecenie bez tworzenia nowego procesush -c /path/to/Program
uruchom proces zależny od powłoki/path/to/Program
uruchom proces zależny od powłoki/path/to/Program 2>&1 &
uruchom niezależny proces powłokinohup /path/to/Program &
uruchom niezależny od powłoki proces i przekieruj wyjście donohup.out
Aktualizacja 1: Mogę zilustrować, na przykład, co to dmenu
jest rekonstrukcja z powtarzających się wywołań ps -efl
w różnych warunkach. Odradza nową powłokę /bin/bash
i jako dziecko tej powłoki aplikacja /path/to/Program
. Tak długo, jak dziecko będzie w pobliżu, tak długo będzie w pobliżu. (Jak sobie z tym radzi, jest to poza mną ...) W przeciwieństwie do tego, jeśli wydajesz nohup /path/to/Program &
z powłoki, /bin/bash
program stanie się dzieckiem tej powłoki, ALE jeśli wyjdziesz z tej powłoki, rodzic programu będzie najwyższym procesem. Więc jeśli pierwszym procesem był np. /sbin/init verbose
I ma, PPID 1
to będzie rodzicem programu. Oto, co próbowałem wyjaśnić za pomocą wykresu: chromium
zostało uruchomione przez dmenu
, firefox
zostało uruchomione za pomocą exec firefox & exit
:
systemd-+-acpid
|-bash---chromium-+-chrome-sandbox---chromium-+-chrome-sandbox---nacl_helper
| | `-chromium---5*[chromium-+-{Chrome_ChildIOT}]
| | |-{Compositor}]
| | |-{HTMLParserThrea}]
| | |-{OptimizingCompi}]
| | `-3*[{v8:SweeperThrea}]]
| |-chromium
| |-chromium-+-chromium
| | |-{Chrome_ChildIOT}
| | `-{Watchdog}
| |-{AudioThread}
| |-3*[{BrowserBlocking}]
| |-{BrowserWatchdog}
| |-5*[{CachePoolWorker}]
| |-{Chrome_CacheThr}
| |-{Chrome_DBThread}
| |-{Chrome_FileThre}
| |-{Chrome_FileUser}
| |-{Chrome_HistoryT}
| |-{Chrome_IOThread}
| |-{Chrome_ProcessL}
| |-{Chrome_SafeBrow}
| |-{CrShutdownDetec}
| |-{IndexedDB}
| |-{LevelDBEnv}
| |-{NSS SSL ThreadW}
| |-{NetworkChangeNo}
| |-2*[{Proxy resolver}]
| |-{WorkerPool/1201}
| |-{WorkerPool/2059}
| |-{WorkerPool/2579}
| |-{WorkerPool/2590}
| |-{WorkerPool/2592}
| |-{WorkerPool/2608}
| |-{WorkerPool/2973}
| |-{WorkerPool/2974}
| |-{chromium}
| |-{extension_crash}
| |-{gpu-process_cra}
| |-{handle-watcher-}
| |-{inotify_reader}
| |-{ppapi_crash_upl}
| `-{renderer_crash_}
|-2*[dbus-daemon]
|-dbus-launch
|-dhcpcd
|-firefox-+-4*[{Analysis Helper}]
| |-{Cache I/O}
| |-{Cache2 I/O}
| |-{Cert Verify}
| |-3*[{DOM Worker}]
| |-{Gecko_IOThread}
| |-{HTML5 Parser}
| |-{Hang Monitor}
| |-{Image Scaler}
| |-{JS GC Helper}
| |-{JS Watchdog}
| |-{Proxy R~olution}
| |-{Socket Thread}
| |-{Timer}
| |-{URL Classifier}
| |-{gmain}
| |-{localStorage DB}
| |-{mozStorage #1}
| |-{mozStorage #2}
| |-{mozStorage #3}
| |-{mozStorage #4}
| `-{mozStorage #5}
|-gpg-agent
|-login---bash---startx---xinit-+-Xorg.bin-+-xf86-video-inte
| | `-{Xorg.bin}
| `-dwm-+-dwmstatus
| `-xterm---bash-+-bash
| `-pstree
|-systemd---(sd-pam)
|-systemd-journal
|-systemd-logind
|-systemd-udevd
|-wpa_actiond
`-wpa_supplicant
Aktualizacja 2: Wydaje mi się, że pytanie można sprowadzić również do: Co powinno być rodzicem procesu? Czy powinien to być np. Powłoka, czy powinien to być init
proces, tj. Proces z PID 1
?
init
- na co odpowiedź może być ... może? zależy to od tego, jak / jeśli planujesz z nim rozmawiać, czegoinit
używasz i gdzie znajdują się kanały danych. Ogólnie rzecz biorąc, rzeczy będą się same układać - po toinit
jest. W każdym razie, zwykle wtedy, gdy demonizujesz procesinit
. Lub jeśli chcesz kontrolować zadania, bieżąca powłoka.dmenu
i zobaczę, jak sobie radzę z tym, czego się nauczyłem. Uważamexec /path/to/Program & exit
lub/bin/bash -c /path/to/Program & exit
być całkiem użyteczne. Ale wszystkie czynią,1
tjinit
. Rodzicem,Program
co jest dla mnie w porządku, o ile ma to sens i nie narusza żadnych podstawowych*nix
zasad.exec &
, że ty. Zwykle robię swoje rzeczy z terminala ... może skorzystasz z pytania Ben Crowella . Mam tam odpowiedź, ale wszystkie są bardzo dobre. tak czy inaczej, kiedy tło procesu, a jego rodzic umiera, to:sh -c 'cat & kill $$'
osierocacie go, a w końcu zostanie skończony. taka jest praca init - dlatego wszyscy do niej należą.systemd--bash--chromium
. Wszystkie metody, które wypróbuję, ostatecznie doprowadzą do drzewa procesu o następującej formie,systemd--chromium
gdy spawnuję firefoxa z powłoki. Jak demonizowana jest tu skorupa? Nie jest powiązany z żadnym terminalem.Odpowiedzi:
Wygląda na to, że dobrze to rozumiesz. Aby wyjaśnić, co masz,
sh -c /path/to/Program
jest dość podobny dotam, gdzie uruchamiasz nowy proces powłoki, podaj ścieżkę polecenia aplikacji do nowej powłoki, a następnie pozwól nowej powłoce zakończyć. Pokazałem nową powłokę podając inny monit w celach ilustracyjnych; prawdopodobnie tak się nie stanie w prawdziwym życiu. Konstrukt jest głównie przydatna robi trudne rzeczy, jak zawijania wielu poleceń w wiązce, tak że wyglądają jak jedno polecenie (rodzaj jednorazowego użytku bezimiennego skryptu), lub budynku skomplikowane polecenia, ewentualnie ze zmiennych powłoki. Prawie nigdy nie używałbyś go tylko do uruchamiania jednego programu z prostymi argumentami.
sh -c "command"
2>&1
oznacza przekierowanie standardowego błędu na standardowe wyjście. To naprawdę nie ma wiele wspólnego z&
; raczej używasz go, gdy polecenie wysyła komunikaty o błędach na ekran, nawet jeśli mówisz i chcesz przechwycić komunikaty o błędach w pliku.command > file
nohup.out
jest trywialnym efektem ubocznymnohup
. Podstawowym celem jest uruchomienie asynchroniczne (powszechnie znane jako „w tle” lub jako „proces niezależny od powłoki”, aby użyć twoich słów) i skonfigurowanie go, aby miał większą szansę na kontynuację, jeśli: zakończ powłokę (np. wyloguj się), gdy polecenie jest nadal uruchomione.nohup command &
command
bash(1)
a Podręcznik referencyjny Bash jest dobrym źródłem informacji.źródło
Istnieje kilka sposobów wykonania programu i odłączenia go od terminala. Jednym z nich jest uruchomienie go w tle podpowłoki , takiej jak ta (zamień na
firefox
swój ulubiony program):Innym jest odrzucenie procesu:
Jeśli jesteś ciekaw, jak wyrzutnie aplikacji do pracy,
dmenu
zapewnia 1 binarny i 2 skrypty powłoki:dmenu
,dmenu_path
idmenu_run
, odpowiednio.dmenu_run
dmenu_path
potokuje wyjście z dmenu, które z kolei potokuje do dowolnej$SHELL
zmiennej. Jeśli jest pusty, użyje/bin/sh
.dmenu_path
jest nieco bardziej skomplikowany, ale w skrócie zawiera listę plików binarnych w$PATH
zmiennej środowiskowej i w miarę możliwości używa pamięci podręcznej.Nie jest konieczne, aby programy działały w powłokach. Innym sposobem pisania
dmenu_run
bez instalowania w powłoce byłoby:źródło
Bardzo podoba mi się odpowiedź G-Mana. Ale odpowiadam, ponieważ myślę, że mylicie obawy. Jak wskazuje Wayne, najlepszą odpowiedzią jest „cokolwiek osiągnie pożądane rezultaty”.
W zarządzaniu procesami uniksowymi każdy proces ma element nadrzędny. Jedynym wyjątkiem jest
init
proces uruchamiany przez system operacyjny podczas rozruchu. Proces nadrzędny jest normalnym zachowaniem, gdy zabiera wszystkie procesy potomne. Odbywa się to poprzez wysłanie sygnału SIGHUP do wszystkich procesów potomnych; domyślna obsługa SIGHUP kończy proces.Odradzanie powłoki procesów użytkownika nie różni się niczym od tego, czy zakodowano wywołania fork (2) / exec (3) w wybranym języku. Powłoka jest twoim rodzicem, a jeśli powłoka się skończy (np. Wylogujesz się), wówczas proces potomny, który ona odradza, idzie z nią w parze. Niuanse, które opisujesz, są tylko sposobami modyfikacji tego zachowania.
exec /path/to/program
jest jak wywołanie exec (3) . Tak, zastąpi twoją powłokęprogram
, zachowując dowolnego rodzica, który uruchomił powłokę.sh -c /path/to/program
rodzaj bezcelowo tworzy proces powłoki potomnej, który utworzy proces potomnyprogram
. Jest to cenne tylko wtedy, gdy w/path/to/program
rzeczywistości jest sekwencją instrukcji skryptu, a nie plikiem wykonywalnym. (sh /path/to/script.sh
może być użyty do uruchomienia skryptu powłoki, który nie ma uprawnień do wykonywania w gorszej powłoce)/path/to/program
tworzy proces „pierwszego planu”, co oznacza, że powłoka czeka na zakończenie procesu przed podjęciem jakichkolwiek innych działań. W kontekście wywołań systemowych przypomina to fork (2) / exec (3) / waitpid (2) . Zauważ, że dziecko dziedziczy stdin / stdout / stderr od rodzica./path/to/program &
(ignorowanie przekierowania) tworzy „proces w tle”. Proces jest nadal potomkiem powłoki, ale rodzic nie czeka na jej zakończenie.nohup /path/to/program
wywołuje nohup (1), aby zapobiec wysłaniu SIGHUP,program
jeśli terminal kontrolny jest zamknięty. To, czy jest to na pierwszym planie, czy w tle, jest wyborem (chociaż najczęściej proces jest w tle). Zauważ, żenohup.out
jest to wynik tylko wtedy, gdy nie przekierujesz stdout w inny sposób.Gdy umieścisz proces w tle, jeśli proces nadrzędny umiera, dzieje się jedna z dwóch rzeczy. Jeśli rodzic jest terminalem kontrolnym , wówczas SIGHUP zostanie wysłany do dzieci. Jeśli tak nie jest, proces może zostać „osierocony” i odziedziczony przez
init
proces.Przekierowując dane wejściowe / wyjściowe / błędy, po prostu podłączasz deskryptory plików, które każdy proces ma do innych plików niż te, które dziedziczy od swojego rodzica. Nic z tego nie wpływa na własność procesu ani głębokość drzewa (ale zawsze sensowne jest przekierowanie wszystkich 3 z dala od terminala dla procesów w tle).
Biorąc to wszystko pod uwagę, nie sądzę, że powinieneś zajmować się tworzeniem procesów przez powłokę, podpowłoki lub podprocesy, chyba że istnieje konkretny problem, który rozwiązujesz związany z zarządzaniem procesami.
źródło
sh -c /path/to/program
nie uruchomi programu jako skryptu powłoki, jeśli brakuje mu bitów wykonywalnych,sh /path/to/program
zrobi to.sh -c /path/to/program
po prostu otworzy powłokę i uruchomi się w niej/path/to/program
jako polecenie, co zakończy się niepowodzeniem, jeśli nie będzie wykonywalna.sh -c /path/to/program
odczytuje polecenia/path/to/program
jako dane wejściowe do powłoki. Plik nie wymaga uprawnień do wykonywania, ale powinien to być skrypt powłokish /path/to/program
robi to. Po prostu spróbowałem tego sam:,echo echo hello world >abc.sh
a następniesh ./abc.sh
drukujehello world
, podczas gdysh -c ./abc.sh
mówish: ./abc.sh: Permission denied
(co jest tak samo, jakbyś uruchomił./abc.sh
bezpośrednio bieżącą powłokę). Czy coś przeoczyłem? (A może niesh -c _something_
to to samo, co pisanie_something_
w wierszu polecenia, z wyjątkiem spawnowania gorszej powłoki. Więc masz rację, że nie powiedzie się, jeśli przegapisz bit wykonawczy (jako plik). Z drugiej strony możesz podać serię poleceń powłoki, takich jaksh -c "echo hello world"
i będzie działać dobrze. Nie wymaga to, aby wpisywane przez Ciebie bity były wykonywane (a nawet być plikiem), tylko interpretator powłoki może coś z tym zrobić.