Linux exec naredba: napredna upotreba u shell-u, C-u i Perl-u

Zadnje ažuriranje: 17/12/2025
Autor: Isaac
  • Exec zamjenjuje pokrenuti program bez promjene PID-a i koristi se zajedno s fork() za učitavanje novih izvršnih datoteka u C i okruženjima. Unix.
  • U ljusci, exec vam omogućuje zamjenu same ljuske ili globalnu rekonfiguraciju deskriptora datoteka i preusmjeravanja.
  • U Perlu, exec i system upravljaju izvršavanjem naredbi naredbe vanjski s različitim ponašanjima, oslanjajući se na funkcije i module poput Shell-a.
  • Savladavanje exec i datotečnih deskriptora ključno je za pisanje robusnih skripti i programa, temeljito kontrolirajući ulaz i izlaz.

exec naredba u Linuxu

Kada ozbiljno počnete raditi s GNU/Linux naredbenim retkom, prije ili kasnije naići ćete na misterioznu naredbu `exec` i C `exec` funkcije u Unix izvršnim programima . U početku je njihovo ponašanje zbunjujuće: ponekad skripta " nestane" i prestane izvršavati retke, drugi put se koristi za izvođenje neobičnih preusmjeravanja datoteka ili za pokretanje udaljenih procesa. Sve zvuči vrlo nisko, ali upravo u tome leži njihova snaga.

U ovom ćemo članku razotkriti tu složenost. Vidjet ćete kako Naredba exec može značiti različite stvari ovisno o tome govorimo li o shell-u, C-u ili čak jezicima poput Perla.i kako se slaže s drugim osnovnim komadima poput fork(), system, deskriptori datoteka ili naredbe kao što su findIdeja je da na kraju dobijete praktičnu i sveobuhvatnu viziju i da vam ruka neće drhtati kada vidite exec u skripti ili u izvornom kodu.

Kako korak po korak stvoriti .deb paket
Povezani članak:
Kako korak po korak stvoriti .deb paket

Što je exec u Unixu/Linuxu: općenita ideja

U Unix kernelu, `exec` je mehanizam za zamjenu trenutno pokrenutog programa drugim unutar istog procesa. Drugim riječima, proces se ne završava i ne stvara novi; umjesto toga, njegova memorijska slika se zamjenjuje onom novog programa. ID procesa (PID) ostaje isti, ali kod i podaci postaju oni nove izvršne datoteke.

S praktičnog gledišta, to znači da C `exec` funkcija nikada ne vraća vrijednost ako sve prođe dobro . Poziv zamjenjuje trenutni program novim, a povratnu vrijednost vidjet ćete samo ako je došlo do pogreške (na primjer, ako izvršna datoteka ne postoji ili nemate dopuštenja).

Ovaj koncept se odražava na nekoliko razina :

  • u Cobitelj funkcija exec* (execl, execv, execve, execvp, Itd.).
  • U ljusci (Bash, sh, itd.): interna naredba exec, koji može zamijeniti ljusku programom ili manipulirati deskriptorima datoteka.
  • U jezicima poput Perla: funkcija exec koji se ponaša slično, s nijansama u usporedbi s system.

Ljepota je u tome što sve ove upotrebe dijele istu temeljnu ideju : zaustaviti izvršavanje onoga što se radilo i, u istom procesu, prijeći na izvršavanje nečeg drugog ili modificirati način na koji taj proces komunicira s vanjskim svijetom putem deskriptora.

Obitelj exec u C-u: zamjena slike procesa

exec funkcije u C-u za Linux

En programiranje sustava s C u Linuxje Obitelj funkcija exec je standardni alat za učitavanje drugog programa u trenutni proces.Obično se pojavljuje uz fork(), koji je odgovoran za stvaranje podređenog procesa.

Opća definicija je da `exec` zamjenjuje memorijski prostor procesa (kod, podatke, stog itd.) prostorom drugog programa. Operativni sustav priprema ovu novu sliku i skače na svoju ulaznu točku kao da se pokrenuo ispočetka, ali ponovno koristeći isti PID.

Najčešće varijacije su:

  • 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[]);

U svima njima, path je apsolutni put do izvršne datoteke, osim u execvpgdje jednostavno možete proslijediti ime i pretraživat će se direktoriji definirani u varijabli okruženja PATHAko se izvršna datoteka distribuira kao AppImage formatPoziv se i dalje primjenjuje. Argumenti novog programa prenose se kao popis varijabli (execl) ili kao niz (execv i tvrtka).

Važno je razumjeti da ove funkcije vraćaju -1 samo ako nisu uspjele (novi program nije izvršen). U normalnom slučaju, izvršavanje se ne vraća na točku poziva jer je procesni kod već drugačiji.

Odnos između fork() i exec(): stvaranje procesa i izvršavanje programa

U Linuxu je uobičajeno jasno razlikovati dva koncepta: stvaranje procesa i pokretanje programa . Proces nije isto što i izvršna datoteka, iako su povezani.

  Popravite crnu pozadinu radne površine u početnom sustavu Windows 10

Za stvaranje novog procesa iz postojećeg, koristite fork()Ovaj poziv, jednostavno rečeno, stvara gotovo identičnu kopiju roditeljskog procesa: isti kod, ista stanja varijabli, iste otvorene datoteke itd. Dijete prima povratnu vrijednost. 0 en fork()dok otac prima sinov PID. Ako nešto pođe po zlu, oboje će vidjeti -1.

Ova kopija nije tako gruba kao što zvuči zahvaljujući tehnikama kao što su Kopiranje prilikom pisanja (COW)Operativni sustav ih koristi za odgađanje stvarnog kopiranja memorijskih stranica dok ih jedan od procesa ne pokuša izmijeniti. Time se izbjegava repliciranje velikih količina memorije samo da bi se odmah odbacile ako se kasnije pozove proces. exec().

Uobičajeno je da se otac brine o stvarajte podprocese s fork() i delegirajte im pravi posaoDijete, jednom stvoreno, izvršava exec() učitati program koji nas zapravo zanima. Na taj način, Otac može nastaviti stvarati više djece ili pričekati da jedno završi. pomoću wait(), što ga blokira dok dijete ne završi.

Kombiniranjem oba dijela često se dobivaju uzorci poput:

  • Otac zove fork().
  • U podređenom procesu poziva se jedna od funkcija. exec* sa željenim programom, kao što je ls -l.
  • Roditelj prati ili sinkronizira djetetov završetak tako što wait().

Ovaj klasični model ima neke Neučinkovitosti nastaju kada se napravi velika kopija procesa samo da bi se odmah zamijenila exec()</codeStoga je važno COW i jasno razumijevanje uloge svakog poziva u životnom ciklusu procesa.

Naredba exec u ljusci: zamjena ljuske i igranje s deskriptorima

Unutar Basha i drugih ljuski, exec To je ugrađeni uređaj s dvije odlične upotrebe: zamijenite ljusku drugom naredbom i izmijenite konfiguraciju deskriptora datoteka te ljuske.

Najizravniji slučaj je kada Usas exec nakon čega slijedi naredba, Na primjer:

exec wall "Mensaje para todos los usuarios"

Ovdje, ljuska koja to izvršava exec prestaje postojati i zamjenjuje se naredbom wallSve što dolazi nakon te linije u skripti neće se izvršiti, jer doslovno ne postoji ljuska koja bi to interpretirala.

Međutim, najzanimljivija upotreba u skriptiranju obično je druga: upotreba exec s preusmjeravanjima za rekonfiguraciju deskriptora datoteka globalno za sesiju ili skriptu. Na primjer, standardni izlaz može ići na /dev/null:

exec 1>/dev/null

Od tada, Bilo koja naredba koju upišete u tu ljusku neće prikazati ništa na ekranujer njegov deskriptor 1 (stdout) pokazuje na /dev/nullMoćna stvar je što ovo utječe na cijelu ljusku, ne samo na određenu naredbu.

Također možete otvoriti dodatni deskriptor povezan s datotekom:

exec 3>>/tmp/salida.log

Na taj način, Deskriptor 3 postaje izlazni kanal za /tmp/salida.logSve što preusmjeravate >&3 Ići će u tu datoteku, dok će ostatak standardnog izlaza ostati na ekranu ili gdje god ste ga postavili.

Važno je zapamtiti da ljuska održava poziciju u datoteci povezanu s deskriptorom . Ako pišete više puta, pokazivač se pomiče; ako zatim pokušate čitati iz tog deskriptora, možda ste već na kraju datoteke i ne dobivate ništa. Kada želite zatvoriti deskriptor, jednostavno:

exec 3>&-

Ovo govori ljusci da prestane koristiti taj kanal. Ovi trikovi su vrlo korisni za strukturiranje logova u složenim skriptama ili odvajanje različitih vrsta izlaza u različite datoteke bez potrebe za preusmjeravanjem svake naredbe pojedinačno.

Napredni primjer shell exec-a: globalna preusmjeravanja

U umjereno složenim pismima uobičajeno je spremi izvorno stanje deskriptora, a zatim ih privremeno preusmjeri za ispis izlaza u zapisnik, privremenu datoteku ili čak u /dev/null.

Tipičan obrazac uključuje prvo kopiranje standardnog izlaza u pomoćni deskriptor, a zatim preusmjeravanje standardnog izlaza u datoteku:

exec 3>&1
exec 1>/tmp/salida.txt

S ovim fragmentom, Deskriptor 3 pokazuje na izlaz koji je deskriptor 1 prethodno imao. ( terminal (normalno), a zatim se deskriptor 1 povezuje s datotekom /tmp/salida.txtOd tada nadalje, sve što se ispiše na stdout iz naredbi skripte ići će u tu datoteku.

Kasnije, kada više ne želite zapisivati ​​u datoteku, možete vratiti početno stanje vraćanjem standardnog izlaza u deskriptor 3 i zatvaranjem potonjeg:

exec 1>&3
exec 3>&-

Nakon ovih redaka, naredbe se vraćaju na prikaz izlaza na zaslonu , a pomoćni deskriptor se oslobađa. Ovo je čisto rješenje za enkapsuliranje dijelova skripte koji se trebaju zapisivati ​​bez zatrpavanja ostatka naredbi preusmjeravanjima.

  Koji je najbolji način za lociranje imena s brojem mobilnog telefona?

Također je moguće preusmjeri standardni ulaz ljuske u datotekutako da sva očitanja od stdin dolaze odatle, što može biti korisno u određenim automatizacijama ili u testovima gdje želite skriptu dati unaprijed snimljene podatke.

Naredba za čitanje i njezin odnos s deskriptorima

Unutar ekosustava ljuske, read To je naredba odgovorna za čitanje sa standardnog ulaza i pohranjivanje rezultata u varijablePrema zadanim postavkama, čita dok ne pronađe prijelom retka, ali njegovo ponašanje se može fino podesiti pomoću nekoliko opcija.

Najjednostavniji način je:

read MIVAR

S ovim, Niz koji tipkate na tipkovnici dok ne pritisnete Enter sprema se u MIVARSasvim je uobičajeno dodati opciju -r tako da se obrnute kose crte ne interpretiraju kao znakovi za izlaz:

read -r MIVAR

Postoje posebno korisne opcije kao što su -pšto vam omogućuje prikaz tekstualnog upita, I -sšto sprječava odjekivanje teksta koji tipkate na ekranuTo je upravo ono što koristite kada želite zatražiti lozinku unutar skripte:

read -s -p "Contraseña: " PASSWD

U ovom slučaju Nećete vidjeti znakove koje upisujete, baš kao kada pokrenete su o sudo, Osim toga, read Usko je povezana sa posebnom varijablom. IFS, koji definira koji se znakovi smatraju razdjelnicima polja (prema zadanim postavkama tabulator, razmak i prijelom retka).

Ako napravite nešto poput:

IFS="-"; read A B C

Naredba će interpretirati znak crtice kao separator , raspoređujući polja za čitanje među varijablama A, B i C. Ako ima više varijabli nego polja, posljednja će biti prazna; ako ima više polja nego varijabli, posljednje će akumulirati sva preostala.

I naravno, Sve se to kombinira s preusmjeravanjima koja konfigurirate execako ste preusmjerili stdin u datoteku, read Dohvatit će podatke odatle umjesto s tipkovnice. Ta fleksibilnost jedan je od temelja dobro dizajniranih shell skripti.

exec u Perlu: razlike sa sustavom i napredna upotreba

U Perlu, koncept exec To je u velikoj mjeri u skladu s ponašanjem u C-u i u shell-u.Ovo se koristi za zamjenu trenutnog procesa drugim programom. Međutim, Perl također nudi systemšto se često miješa s exec čak i ako ne rade istu stvar.

Funkcija system Pokreće vanjsku naredbu i čeka da se završi, vraćajući kontrolu skripti.. Umjesto toga, exec Potpuno zamjenjuje Perl proces s pozvanim programom i ne vraća se u skriptu.osim u slučaju pogreške. Vrlo jednostavan primjer bio bi:

exec 'cat -n /etc/passwd';
die "no se pudo ejecutar cat: $!";

Si poziv na exec Ako uspije, nikada neće biti izvršeno. diejer će Perl interpreter biti zamijenjen binarnim catAko ne uspije (na primjer, zato što ne postoji) cat), zatim se izvršava die prikaz poruke o pogrešci i vrijednosti $!.

Jedan vrlo koristan detalj je taj, baš kao i s system, možete prizvati exec s popisom argumenata za sprječavanje interpretacije metakaraktera ljuske, Na primjer:

exec '/bin/echo', 'Los argumentos son: ', @ARGV;

Ako pokrenete taj skript ovako:

./exec.pl 'uno' '| ls ' '| who > quien'

Vidjet ćete to argumenti koji uključuju | ili preusmjeravanja ne aktiviraju ljuskuali se prenose kakvi jesu /bin/echoIzlaz bi bio nešto poput ovoga:

Los argumentos son: uno | ls  | who > quien

Drugim riječima, nijedna naredba zapravo nije izvršena ; prikazani su samo tekstovi.

Korištenje naredbe exec u Perlu za pripremu okruženja za izvođenje

Osim jednostavnih primjera, Perl se lako koristi za izradu skripti koje sofisticirano pripremaju radno okruženje prije pokretanja drugog programa . Tipičan slučaj je kada ćete pokretati zadatke na udaljenim računalima putem SSH- a i želite ponovno stvoriti određene kontekste lokalnog procesa.

Uobičajeni pristup je imati potprogram koji dinamički gradi privremeni skript, a zatim ga izvršavaU toj skripti možete postaviti radni direktorij, varijable okruženja ili ponašanje signala i na kraju koristiti system o exec ovisno o tome želimo li se vratiti na ambalažu ili ne.

  Potpuni vodič za integraciju OneNotea u Microsoft Teams: koraci, vrste i najbolje prakse

Na primjer, mali program može se pohraniti u višelinijski niz koji:

  • Promjena u izvorni direktorij iz kojeg je pozvan glavni skript.
  • Vrati varijable okruženja iz serijaliziranog popisa.
  • Izvršite stvarnu naredbu s system, provjeravajući njegov izlazni status.
  • Izbriši privremenu skriptu i završava eksplicitno s exit(0).

Prije spremanja programa u privremenu datoteku, tekstualni rezervirani prostori (direktorij, naredba za izvršavanje, naziv skripte itd.) zamjenjuju se stvarnim vrijednostima. Ova tehnika omogućuje vam da enkapsulirate svu logiku pripreme okruženja i imate jednu ulaznu točku koja jednostavno "omotava" svako udaljeno izvršavanje.

Ova vrsta rješenja u potpunosti iskorištava Perlova sposobnost manipuliranja stringovima, datotekama i procesimai vrlo dobro se uklapa u funkcije exec y system kada su u distribuiranim sustavima potrebna vrlo specifična ponašanja.

Perlov Shell modul i implicitno pozivanje naredbi

Još jedan zanimljiv aspekt vezan uz Izvršavanje vanjskih naredbi u Perlu je modul ShellOvaj modul vam omogućuje pozivanje sistemskih programa kao da su Perl funkcije, zahvaljujući korištenju AUTOLOAD.

Zamislite da učitavamo modul ovako:

use Shell qw(echo cat ps cp);

Od tog trenutka nadalje , kada napišete nešto poput:

$foo = echo("howdy", "funny", "world");

Ono što se događa ispod je to Perl ne može pronaći potprogram pod nazivom echo i puca AUTOLOAD modulaOvaj mehanizam:

  • Odredite naziv naredbe počevši od punog naziva potprograma (Shell::echo).
  • Dinamički konstruirajte stvarnu funkciju koji će izvršiti tu sistemsku naredbu.
  • Proslijedi poziv na novu značajku, prenoseći primljene argumente.

Ako pregledate izvršenje pomoću Perl debuggera, vidjet ćete kako Argumenti su organizirani u @_ i konstruira se naredba koja će se pokrenuti.Rezultat trčanja echo Sakuplja se i pohranjuje u $foo, tako da:

print $foo;

Pokazat će nešto od stila howdy funny world s formatom koji generira echo sustavaOvaj pristup je praktičan, ali se ne smije pretjerano koristiti jer može otežati čitljivost koda i rukovanje greškama.

Naredba exec u ljusci kao napredni alat za preusmjeravanje

Kao što smo vidjeli, naredba exec U ljusci se ne koristi samo za zamjenu ljuske.Umjesto toga, često se koristi za otvaranje, zatvaranje ili dupliciranje deskriptora datoteka. Ova mogućnost omogućuje stvaranje vrlo moćnih obrazaca u skriptama.

Na primjer, možda biste htjeli trajno preusmjeri izlaz cijelog skripta u datoteku dnevnika bez potrebe za >>log.txt u svakom retku. Nešto poput:

exec >/var/log/mi_script.log 2>&1

Na ovaj način, i standardni izlaz i izlaz greške će ići u istu datoteku od početka skripte. Od tada nadalje, svaka naredba koja ne uspije ostavit će trag u zapisniku bez zatrpavanja terminala.

U drugim slučajevima, možda će vas zanimati pridružiti određene deskriptore privremenim datotekama za spremanje podataka koje ćete kasnije obraditi. Zatvaranjem tih deskriptora s exec n>&-Oslobađate resurse i sprječavate curenje rukovatelja.

Istina je da se ova vrsta konstrukcije ne vidi u osnovnim skriptama, ali kada počnete pisati ozbiljne administratorske uslužne programe, oni postaju gotovo neophodni za pravilnu kontrolu onoga što se vidi na ekranu, što se sprema i kako su informacije strukturirane.

U konačnici, savladavanje exec-a kao naprednog alata za preusmjeravanje daje vam razinu kontrole nad shell skriptnim I/O operacijama koja čini razliku između "domaćih" skripti i robusnih produkcijskih alata.

Na kraju cijelog ovog putovanja, ključna ideja je da Naredba exec, bilo u C-u, shell-u ili Perl-u, uvijek se vrti oko dvije osi: zamjene programa koji se izvršava i preciznog upravljanja ulazima i izlazima.Razumijevanje kako se kombiniraju s fork(), system, read ili moduli poput Shell Omogućuje vam dizajniranje čišćih, učinkovitijih i sigurnijih rješenja, bilo da se radi o pokretanju udaljenih procesa, enkapsulaciji složenih okruženja za izvršavanje ili jednostavnom pisanju skripti koje rade točno ono što želite, bez iznenađenja.