Kontrola zdravého rozumu:Pokud jsem pochopil, shell je rozhraní, přes které může uživatel komunikovat s OS, tj.:spouštět další procesy.
Ano, ale „shell“ je konkrétně uživatel rozhraní, nikoli programovací rozhraní. Jiné programy s ním nemusejí komunikovat – mohou přímo používat stejná systémová volání k vytváření nových procesů.
Takže shell příkazového řádku je na stejné úrovni jako ostatní programy, např. správce služeb nebo grafická uživatelská rozhraní (grafické shelly).
Ačkoli shell (např. Bash) je jen další proces.
Ano. Na systémech podobných Unixu je to zcela normální, neprivilegovaný proces.
Existuje způsob, jak spustit proces, který nebude potomkem procesu shellu?
Z pohledu uživatele:ano, existuje několik způsobů.
-
Většina shellů má
exec
klíčové slovo, které způsobí, že nový program nahradí shell (zachování stejného PID a rodičovství), což pravděpodobně není to, co jste mysleli, ale technicky to, co jste požadovali. -
Relace grafické plochy se často spouštějí bez vyvolání bash nebo jakéhokoli jiného prostředí, a to se automaticky vztahuje na aplikace spouštěné prostřednictvím grafických nabídek. Rodičem aplikace bude jakýkoli proces, který byl zodpovědný za zobrazení nabídky (např. správce oken nebo panel).
-
V současnosti populární systemd init systém při spouštění služeb vůbec nepoužívá shell, takže můžete definovat .službu a spustit ji – rodičem služby bude samotný init. Má také funkci umožňující vytváření dočasných služeb za běhu pomocí
systemd-run
, se stejnými výsledky.
Z pohledu programátora stačí použít fork()
a execve()
systémová volání ke spuštění nového procesu. (Existují podrobnosti specifické pro operační systém, např. fork() může být ve skutečnosti obal pro jiné volání, ale stále funguje stejným způsobem.)
I kdyby chtěl program vyvolat shell, udělal by to vytvořením nového podřízeného procesu a spuštěním /bin/sh pomocí stejného fork+exec. Pro spuštění shellu neexistuje žádné speciální systémové volání. (Programátor by mohl použít např. system() při psaní v C nebo os.system() v Pythonu, ale to jsou stále jen praktické obaly kolem fork/exec.)
Proměnné prostředí:V bash existuje několik skriptů, které se spustí, když vytvoříte shell, např. .bashrc, .bash_profile atd. (záleží na typu shellu – interaktivní vs neinteraktivní, přihlášení vs nepřihlášení). Tyto skripty definují proměnné prostředí. Pokud existuje způsob, jak spustit proces bez ohledu na jakýkoli shell, odkud pocházejí proměnné prostředí?
No, někdy ne. (Je to skutečný praktický problém, když se snažíte, aby grafické aplikace přebíraly přizpůsobení prostředí v závislosti na tom, jak konkrétní grafické prostředí začíná.)
Celkově však proměnné prostředí nejsou unikátní pro shelly CLI. Každý proces, bez ohledu na to, jak byl spuštěn (včetně procesu init), obdrží pole řetězců obsahujících jeho příkazový řádek – a pole řetězců obsahujících jeho proměnné prostředí. Při spouštění podřízeného procesu může buď určit jiné prostředí, nebo umožnit zdědění kopie vlastního prostředí.
Takže když se přihlásíte, váš shell již obdrží několik počátečních proměnných prostředí od svého rodiče. Tyto spouštěcí skripty (bashrc atd.) jsou jen vhodným místem pro uživatele k přizpůsobení proměnných prostředí, které potom podřízené procesy shellu zdědí.
Mnoho částí této odpovědi plně platí i pro Windows – ačkoliv je jeho grafické rozhraní o něco složitější, CLI shelly (cmd.exe a PowerShell) jsou stále běžné programy, které se v běžném provozu vůbec nepoužívají. Jediný hlavní rozdíl je v tom, že Windows má jediné volání „CreateProcess“ namísto samostatných volání „fork + exec“ ve stylu Unixu.
-
To je správně. Nakonec shell provede
exec
systémové volání, které je dostupné ve všech operačních systémech kompatibilních s POSIX a obecněji ve všech operačních systémech podobných Unixu, včetně Linuxu. Ostatní operační systémy mají podobný koncept. V systému Linuxexec
systémové volání nakonec zavoláexecve
funkce, která je poskytována jádrem a provádí skutečnou práci načtení spustitelného souboru a jeho spuštění. -
Ano. Jakýkoli proces může volat
exec
a nemusí to být "skořápka". Když například spustíte program kliknutím v prohlížeči souborového systému, software pro stolní počítače provedeexec
volání, není tam žádná skořápka. Všimněte si, že proces se stane potomkem desktopového softwaru, který jej spustil. Všechny procesy jsou potomky jednoho dalšího procesu, kromě úplně prvního, který se nazýváinit
a má PID 1. Zodpovídá za nastavení operačního systému při startu a spouštění všech dalších procesů, jako jsou služby na pozadí a přihlašování na plochu. Na Linuxu dnessystemd
se často používá jakoinit
procesu, ale existují i jiné alternativy. -
Existuje několik variant
exec
(execl
,execle
, ...), které mají kromě názvu programu, který má být spuštěn, různé argumenty. Nakonecexecve
systémové volání přebírá název programu, seznam řetězců, které jsou argumenty příkazového řádku, a seznam řetězců, které jsou proměnnými prostředí. Například při spouštění softwaru z prohlížeče souborového systému mohou být proměnné prostředí zkopírovány z proměnných samotného prohlížeče souborového systému, případně modifikovány prohlížečem souborového systému. To je zcela na programátorech prohlížeče souborového systému.
Další čtení:
- https://en.wikipedia.org/wiki/Exec_(system_call)
- https://cs.wikipedia.org/wiki/Fork%E2%80%93exec
- https://man7.org/linux/man-pages/man2/execve.2.html