- Funkce Exec nahrazuje běžící program bez změny PID a používá se ve spojení s fork() k načítání nových spustitelných souborů v jazyce C a dalších prostředích. Unix.
- V shellu vám exec umožňuje nahradit samotný shell nebo globálně překonfigurovat deskriptory souborů a přesměrování.
- V Perlu spravují exec a system provádění příkazů příkazy externí s různým chováním, spoléhající se na funkce a moduly, jako je Shell.
- Zvládnutí exec a souborových deskriptorů je klíčem k psaní robustních skriptů a programů a důkladné kontrole vstupu a výstupu.

Když začnete vážně pracovat s příkazovým řádkem GNU/Linuxu, dříve či později narazíte na záhadný příkaz exec a funkce exec v jazyce C Spustitelné programy v UnixuZpočátku je jeho chování znepokojivé: někdy skript „Zmizí“ a zastaví provádění řádků; jindy se používá k provádění neobvyklých přesměrování souborů nebo ke spouštění vzdálených procesů. To vše zní velmi nízkoúrovňově, ale právě v tom spočívá jeho síla.
V tomto článku se chystáme tuto složitost rozluštit. Uvidíte, jak Příkaz exec může znamenat různé věci v závislosti na tom, zda mluvíme o shellu, jazyku C nebo dokonce o jazycích jako Perl.a jak se hodí k dalším základním kouskům, jako je fork(), system, deskriptory souborů nebo příkazy jako například findJde o to, abyste nakonec získali praktickou a komplexní vizi a aby se vám ruka netřásla, když uvidíte exec ve skriptu nebo ve zdrojovém kódu.
Co je exec v Unixu/Linuxu: obecná představa
V unixovém jádře je exec mechanismem pro nahrazení aktuálně spuštěného programu. jiným v rámci stejného procesu. To znamená, že proces neumře a nevytvoří nový, ale jeho „obraz paměti“ je nahrazen obrazem nového programu. PID zůstává stejný, ale kód a data se stávají kódy a daty nového spustitelného souboru.
Z praktického hlediska to znamená, že Funkce exec v jazyce C se nikdy nevrátí, pokud vše proběhne dobře.Volání nahradí aktuální program novým a návratovou hodnotu uvidíte pouze v případě, že došlo k chybě (například spustitelný soubor neexistuje nebo nemáte oprávnění).
Tato koncepce se odráží v různé úrovně:
- v Crodina funkcí
exec*(execl,execv,execve,execvp, Atd.). - Ve skořápce (Bash, sh atd.): interní příkaz
exec, který může nahradit shell programem nebo manipulovat s deskriptory souborů. - V jazycích jako Perlfunkce
execkterý se chová podobně, s nuancemi ve srovnání ssystem.
milost je to Všechna tato použití sdílejí stejnou základní myšlenku: zastavit provádění toho, co se dělalo, a zároveň přejít k provádění něčeho jiného, o upravit způsob, jakým daný proces komunikuje s okolním světem prostřednictvím deskriptorů.
Rodina exec v jazyce C: nahrazení obrazu procesu

En programování systémů s C v Linux, Rodina funkcí exec je standardní nástroj pro načítání jiného programu do aktuálního procesu.Obvykle se objevuje vedle fork(), který je zodpovědný za vytvoření podřízeného procesu.
Obecná definice je, že exec nahrazuje paměťový prostor procesu (kód, data, zásobník atd.) s obrazem jiného programu. Operační systém připraví tento nový obraz a přejde na jeho vstupní bod, jako by se spustil od nuly, ale znovu použije stejný PID.
the nejběžnější varianty Zvuk:
int execl(const char *path, const char *arg, ...);int execv(const char *path, char * const argv[]);int execve(const char *path, char * const argv[], char * const envp[]);int execvp(const char *file, char * const argv[]);
Ve všech z nich, path je absolutní cesta k spustitelnému souboru, s výjimkou execvpkde můžete jednoduše předat název a program bude vyhledávat v adresářích definovaných v proměnné prostředí PATHPokud je spustitelný soubor distribuován jako Formát AppImageVolání stále platí. Argumenty nového programu se předávají jako seznam proměnných (execl) nebo jako pole (execv a společnost).
Je důležité to pochopit Tyto funkce vracejí -1 pouze v případě, že selhaly. (Nový program ještě nebyl spuštěn.) V normálním případě se provádění nevrací do bodu volání, protože kód procesu je již jiný.
Vztah mezi fork() a exec(): vytváření procesů a spouštění programů
V Linuxu je zvykem jasně rozlišovat mezi Dvě myšlenky: vytvářet procesy a spouštět programyProces není totéž co spustitelný soubor, ačkoli spolu souvisí.
Chcete-li vytvořit nový proces z existujícího, použijete fork()Toto volání, jednoduše řečeno, vytvoří téměř identickou kopii rodičovského procesu: stejný kód, stejné stavy proměnných, stejné otevřené soubory atd. Dítě obdrží návratovou hodnotu. 0 en fork()zatímco otec obdrží synův PID. Pokud se něco pokazí, oba uvidí -1.
Tato kopie není tak hrubá, jak zní, a to díky technikám, jako je Kopírování při zápisu (COW)Tyto parametry používá operační systém k odložení skutečného kopírování paměťových stránek, dokud se je jeden z procesů nepokusí upravit. Tím se zabrání replikaci velkého množství paměti, které by se pak v případě pozdějšího volání procesu okamžitě zahodilo. exec().
Je obvyklé, že se o to stará otec vytvořit podřízené procesy s fork() a delegovat na ně skutečnou práciJakmile je dítě vytvořeno, provede exec() načíst program, který nás skutečně zajímá. Tímto způsobem Otec může pokračovat ve vytváření dalších dětí nebo počkat, až jedno dokončí. pomocí wait(), který jej blokuje, dokud dítě nedokončí.
Spojením obou částí obvykle dojde k patrones jako:
- Otec volá
fork(). - V podřízeném procesu je volána jedna z funkcí.
exec*s požadovaným programem, jako např.ls -l. - Rodič sleduje nebo synchronizuje dokončení úkolů dítěte
wait().
Tento klasický model má několik Neefektivita vzniká, když se vytvoří velká kopie procesu, která je okamžitě nahrazena novými... exec()</codeProto je důležité COW a jasné pochopení role každého volání v životním cyklu procesu.
Příkaz exec v shellu: nahrazení shellu a hraní si s deskriptory
V rámci Bash a dalších shellů, exec Je to vestavěný prvek se dvěma skvělými využitími: nahradit shell jiným příkazem a upravit konfiguraci deskriptorů souborů daného shellu.
Nejpřímějším případem je, když nás jako exec následovaný příkazem. Například:
exec wall "Mensaje para todos los usuarios"
Zde, shell, který to spouští exec přestává existovat a je nahrazen příkazem wallVšechno, co ve skriptu následuje po tomto řádku, nebude provedeno, protože doslova nezbývá žádný shell, který by to interpretoval.
Nejzajímavější využití ve skriptování je však obvykle to druhé: použití exec s přesměrováním pro překonfigurování deskriptorů souborů globálně pro relaci nebo skript. Například můžete mít standardní výstup odeslaný na /dev/null:
exec 1>/dev/null
Od té doby, Žádný příkaz, který v tomto shellu zadáte, na obrazovce nic nezobrazí.protože jeho deskriptor 1 (stdout) ukazuje na /dev/nullVýhodou je, že to ovlivňuje celý shell, nejen konkrétní příkaz.
Můžete také otevřít další deskriptor přidružený k souboru:
exec 3>>/tmp/salida.log
Tímto způsobem Deskriptor 3 se stává výstupním kanálem pro /tmp/salida.logVšechno, s čím přesměrováváte >&3 Přejde do tohoto souboru, zatímco zbytek standardního výstupu zůstane na obrazovce nebo kdekoli jinde, kde ho máte nastavený.
Je důležité si uvědomit, že shell si v souboru uchovává pozici přidruženou k deskriptoru.Pokud píšete vícekrát, ukazatel se posune; pokud se pak pokusíte číst z daného deskriptoru, můžete být již na konci souboru a nic se nedostanete. Chcete-li deskriptor zavřít, jednoduše:
exec 3>&-
Toto říká shellu, aby přestal daný kanál používat. Triky Jsou velmi užitečné pro struktura protokoly ve složitých skriptech nebo oddělit různé typy výstupu do různých souborů aniž by bylo nutné přesměrovávat každý příkaz jednotlivě.
Pokročilý příklad shellu exec: globální přesměrování
V středně propracovaných písmech je běžné uložit původní stav deskriptorů a poté je dočasně přesměrovat uložit výstup do protokolu, dočasného souboru nebo dokonce do /dev/null.
Typický vzorec se skládá z nejprve zkopírujte standardní výstup do pomocného deskriptoru a poté přesměrovat standardní výstup do souboru:
exec 3>&1
exec 1>/tmp/salida.txt
S tímto fragmentem, Deskriptor 3 ukazuje na výstup, který dříve měl deskriptor 1. (dále jen terminál (normálně) a poté je deskriptor 1 připojen k souboru /tmp/salida.txtOd té chvíle se vše, co se z příkazů skriptu vypíše na stdout, bude odesílat do tohoto souboru.
Později, když již nebudete chtít pokračovat v nahrávání do souboru, můžete obnovit původní stav vrácení standardního výstupu do deskriptoru 3 a jeho uzavření:
exec 1>&3
exec 3>&-
V návaznosti na tyto řádky, Příkazy opět zobrazují svůj výstup na obrazovce.a je vydán pomocný deskriptor. Je to čisté řešení pro zapouzdření částí skriptu, které je třeba protokolovat, aniž by se zbytek příkazů zahlcoval přesměrováním.
Je také možné přesměrovat standardní vstup shellu do souborutakže všechny hodnoty stdin pocházejí odtud, což může být užitečné v konkrétních automatizacích nebo v testech, kde chcete skriptu poskytnout předem nahraná data.
Příkaz read a jeho vztah k deskriptorům
V rámci ekosystému skořápek, read Je to příkaz zodpovědný za čtení ze standardního vstupu a ukládání výsledku do proměnných.Ve výchozím nastavení čte, dokud nenajde zalomení řádku, ale jeho chování lze doladit pomocí několika možností.
nejjednodušší způsob Je to:
read MIVAR
S tím, Řetězec, který píšete na klávesnici, dokud nestisknete klávesu Enter, se ukládá do MIVARJe docela běžné přidat tuto možnost -r aby zpětná lomítka nebyla interpretována jako řídicí znaky:
read -r MIVAR
Existují obzvláště užitečné možnosti, jako například -pkterý umožňuje zobrazit text výzvyA -scož zabraňuje ozvěnám psaného textu na obrazovcePřesně to použijete, když chcete ve skriptu požádat o heslo:
read -s -p "Contraseña: " PASSWD
V tomto případě Neuvidíte zadané znaky, stejně jako když spustíte su o sudo, Také, read Je úzce spojena se speciální proměnnou. IFS, který definuje, které znaky jsou považovány za oddělovače polí (ve výchozím nastavení tabulátor, mezera a zalomení řádku).
Pokud uděláte něco jako:
IFS="-"; read A B C
Objednávka bude interpretovat pomlčku jako oddělovačRozdělení polí pro čtení mezi proměnné A, B a C. Pokud je proměnných více než polí, budou pole prázdná; pokud je polí více než proměnných, Poslední z nich nashromáždí všechny zbývající..
A samozřejmě, To vše je kombinováno s přesměrováními, která nakonfigurujete pomocí execPokud jste přesměrovali stdin do souboru, read Bude načítat data odtud místo z klávesnice. Tato flexibilita je jedním ze základních kamenů dobře navržených shellových skriptů.
exec v Perlu: rozdíly se systémem a pokročilé použití
V Perlu je koncept exec Je to velmi v souladu s chováním v jazyce C a v shellu.Toto se používá k nahrazení aktuálního procesu jiným programem. Perl však také nabízí systemkterý se často zaměňuje s exec i když nedělají totéž.
Funkce system Spustí externí příkaz a čeká na jeho dokončení, čímž vrátí řízení skriptu.. Namísto, exec Zcela nahrazuje proces Perlu volaným programem a nevrací se do skriptu.s výjimkou případu chyby. Velmi základní příklad by byl:
exec 'cat -n /etc/passwd';
die "no se pudo ejecutar cat: $!";
Si volání k exec Pokud se to podaří, nikdy se to neprovede. dieprotože interpret Perlu bude nahrazen binárním souborem catPokud selže (například proto, že neexistuje) cat), pak se provede die zobrazení chybové zprávy a hodnoty $!.
Jeden velmi užitečný detail je, stejně jako s system, můžete přivolat exec se seznamem argumentů, které zabraňují interpretaci metaznaků shellu. Například:
exec '/bin/echo', 'Los argumentos son: ', @ARGV;
Pokud spustíte tento skript takto:
./exec.pl 'uno' '| ls ' '| who > quien'
Uvidíte to argumenty, které zahrnují | nebo přesměrování neaktivuje shellale jsou převedeny tak, jak jsou /bin/echoVýstup by byl něco takového:
Los argumentos son: uno | ls | who > quien
To znamená, že žádný příkaz ve skutečnosti nebyl proveden, zobrazeny byly pouze texty.
Použití exec v Perlu k přípravě běhového prostředí
Kromě jednoduchých příkladů, Perl se hodí k vytváření skriptů, které sofistikovaně připraví pracovní prostředí před spuštěním dalšího programu.Typickým případem je, když se chystáte spustit úlohy na vzdálených počítačích prostřednictvím SSH a chcete znovu vytvořit určitý kontext místního procesu.
Běžným přístupem je mít podprogram, který dynamicky vytvoří dočasný skript a poté jej spustíV tomto skriptu můžete nastavit pracovní adresář, proměnné prostředí nebo chování signálu a nakonec použít system o exec v závislosti na tom, zda se chceme k obalu vrátit, či nikoli.
Například může být uložen v víceřádkový řetěz malý program, který:
- Změna do původního adresáře ze kterého byl vyvolán hlavní skript.
- Obnovit proměnné prostředí ze serializovaného seznamu.
- Proveďte skutečný příkaz s
systema kontroluje jeho výstupní stav. - Smazat dočasný skript a končí explicitně slovy
exit(0).
Před uložením programu do dočasného souboru, Textové značky jsou nahrazeny (adresář, příkaz ke spuštění, název skriptu atd.) s jejich skutečnými hodnotami. Pomocí této techniky můžete zapouzdřit veškerou logiku přípravy prostředí a mít jeden vstupní bod, který jednoduše „zabalí“ jakékoli vzdálené spuštění.
Tento typ řešení plně využívá Schopnost Perlu manipulovat s řetězci, soubory a procesya velmi dobře se hodí k funkcím exec y system když je v distribuovaných systémech vyžadováno velmi specifické chování.
Perlský shellový modul a implicitní volání příkazů
Další kuriózní aspekt související s Spouštění externích příkazů v Perlu je modul ShellTento modul umožňuje volat systémové programy, jako by to byly funkce Perlu, a to díky použití... AUTOLOAD.
Představte si, že modul načtete takto:
use Shell qw(echo cat ps cp);
Od té chvíle, když napíšete něco jako:
$foo = echo("howdy", "funny", "world");
Co se děje dole, je to, Perl nemůže najít podprogram s názvem echo a výhonky AUTOLOAD moduluTento mechanismus:
- Určete název příkazu počínaje celým názvem podprogramu (
Shell::echo). - Dynamicky sestavte reálnou funkci který provede daný systémový příkaz.
- Přesměrování hovoru na novou funkci, s předáním obdržených argumentů.
Pokud si prohlédnete spuštění pomocí debuggeru Perlu, uvidíte, jak Argumenty jsou uspořádány do @_ a je sestaven příkaz, který má být spuštěn.Výsledek běhu echo Je shromažďován a ukládán v $foo, takže:
print $foo;
Ukáže to něco ze stylu howdy funny world s formátem, který generuje echo systémuTento přístup je pohodlný, ale neměl by se nadužívat, protože může ztížit čitelnost kódu a ošetření chyb.
Příkaz exec v shellu jako pokročilý nástroj pro přesměrování
Jak jsme viděli, příkaz exec Ve skořápce se nepoužívá pouze k nahrazení skořápky.Místo toho se často používá k otevírání, zavírání nebo duplikování deskriptorů souborů. Tato schopnost umožňuje vytvářet velmi účinné vzory ve skriptech.
Například byste mohli chtít trvale přesměrovat výstup celého skriptu do souboru protokolu aniž by museli >>log.txt na každém řádku. Něco jako:
exec >/var/log/mi_script.log 2>&1
S tím, Standardní výstup i chybový výstup půjdou do stejného souboru. Od začátku skriptu. Od té chvíle každý neúspěšný příkaz zanechá stopu v protokolu, aniž by zahlcoval terminál.
V jiných případech by vás mohlo zajímat přiřadit specifické deskriptory k dočasným souborům pro uložení dat, která budete později zpracovávat. Uzavřením těchto deskriptorů pomocí exec n>&-Uvolníte zdroje a zabráníte únikům obslužných rutin.
Je pravda, že tento typ konstrukce se v základních písmech nevyskytuje, ale Když začnete psát, seriózní administrativní nástroje se stanou téměř nepostradatelnými. správně kontrolovat, co se zobrazuje na obrazovce, co se ukládá a jak jsou informace strukturovány.
Zkrátka, zvládnout exec jako pokročilý nástroj pro přesměrování vám poskytuje určitou úroveň kontroly nad skriptováním shellu I/O. což je rozdíl mezi „domácími“ scénáři a robustními produkčními nástroji.
Na konci celé této cesty je klíčovou myšlenkou, že Funkce exec, ať už v jazyce C, shellu nebo Perlu, se vždy točí kolem dvou os: nahrazení běžícího programu a přesná správa vstupů a výstupů.Pochopení toho, jak se kombinují s fork(), system, read nebo moduly jako Shell Umožňuje vám navrhovat čistší, efektivnější a bezpečnější řešení, ať už jde o spouštění vzdálených procesů, zapouzdření složitých spouštěcích prostředí nebo jednoduše psaní skriptů, které dělají přesně to, co chcete, bez překvapení.
Vášnivý spisovatel o světě bytů a technologií obecně. Rád sdílím své znalosti prostřednictvím psaní, a to je to, co budu dělat v tomto blogu, ukážu vám všechny nejzajímavější věci o gadgetech, softwaru, hardwaru, technologických trendech a dalších. Mým cílem je pomoci vám orientovat se v digitálním světě jednoduchým a zábavným způsobem.
