Cum să rulați și să controlați procesele de fundal pe Linux

Folosește terminalul Bash în Linux pentru a administra procesele active și cele care rulează în fundal. Funcțiile de control al joburilor din Bash îți oferă o mai mare flexibilitate în modul în care execuți comenzile. Vom explora împreună cum funcționează aceste mecanisme.

Despre Procese

Atunci când un program este lansat într-un sistem Linux sau Unix, se inițiază un proces. Un „proces” este reprezentarea internă a programului care este activ în memoria calculatorului. Fiecare program activ are un proces corespunzător. De fapt, aproape tot ceea ce funcționează pe sistemul tău este asociat cu un proces, inclusiv mediul desktop grafic (GDE) precum GNOME sau KDE și daemonii care pornesc automat la inițializarea sistemului.

De ce spunem „aproape tot”? Deoarece comenzile integrate în Bash, cum ar fi cd, pwd și alias, nu necesită un proces separat pentru a fi executate. Bash le procesează direct în instanța de shell activă în fereastra terminalului. Acesta este motivul pentru care aceste comenzi se execută rapid, evitând inițierea unui nou proces. Poți consulta lista completă a comenzilor integrate folosind comanda `help` în terminal.

Procesele pot rula în prim-plan, caz în care preiau controlul terminalului până la finalizare, sau în fundal, unde nu blochează fereastra terminalului și îți permit să continui lucrul în același timp. Totuși, procesele din fundal nu vor interfera cu activitatea ta doar dacă nu generează ieșiri pe ecran.

Exemplu Practic

Vom simula o comandă `ping` către un site web, folosind ca exemplu domeniul How-To Geek. Inițial, comanda va rula ca proces în prim-plan.

ping www.wdzwdz.com

Rezultatele comenzii vor fi afișate în terminal. În acest timp, terminalul este blocat, iar tu nu vei putea introduce alte comenzi. Pentru a opri comanda `ping`, trebuie să apeși tastele Ctrl+C.

Ctrl+C

După ce apeși Ctrl+C, comanda `ping` afișează un scurt rezumat și se încheie. Acum vom repeta aceeași comandă, dar de data aceasta vom apăsa Ctrl+Z în loc de Ctrl+C. Comanda nu se va încheia, ci va fi trimisă în fundal, iar noi vom recupera controlul asupra terminalului.

ping www.wdzwdz.com
Ctrl+Z

După Ctrl+Z, procesul va fi oprit, adică nu se va încheia, ci doar va fi pus în pauză. Este ca o mașină la stop, care așteaptă să fie repornită. Acum, procesul rulează ca un job în fundal.

Comanda `jobs` afişează lista joburilor active în sesiunea curentă de terminal. Deoarece joburile sunt de fapt procese, putem folosi și comanda `ps` pentru a le vizualiza. Vom folosi ambele comenzi și vom compara rezultatele, utilizând opțiunea `T` pentru `ps`, care listează procesele care rulează în terminalul curent (nu este necesară cratima înaintea lui `T`).

jobs
ps T

Comanda `jobs` ne spune:

  • `[1]`: Numărul din paranteze este numărul jobului, folosit pentru a face referire la joburile active prin comenzile de control.
  • `+`: Simbolul `+` indică faptul că acesta este jobul implicit, cel care va fi afectat dacă folosim comenzi de control fără a specifica numărul jobului. Jobul implicit este întotdeauna cel adăugat cel mai recent.
  • `Oprit`: Procesul este în prezent oprit.
  • `ping www.wdzwdz.com`: Comanda care a fost utilizată pentru a iniția procesul.

Comanda `ps` ne spune:

  • `PID`: Identificatorul unic al procesului.
  • `TTY`: Terminalul de pe care a fost executat procesul.
  • `STAT`: Starea procesului.
  • `TIME`: Timpul CPU utilizat de proces.
  • `COMMAND`: Comanda care a inițiat procesul.

Valori posibile pentru coloana `STAT`:

  • `D`: Procesul este într-o stare de așteptare neîntreruptibilă, așteptând de obicei o intrare sau ieșire și nu poate fi întrerupt.
  • `I`: Inactiv.
  • `R`: În execuție.
  • `S`: În stare de așteptare întreruptibilă.
  • `T`: Oprit printr-un semnal de control al jobului.
  • `Z`: Proces zombi; procesul s-a încheiat, dar nu a fost curățat de procesul părinte.

Valoarea din coloana STAT poate fi urmată de indicatori suplimentari:

<`:Proces cu prioritate ridicată. `N:Proces cu prioritate scăzută. `L:Proces cu pagini blocate în memorie. `S:Liderul unei sesiuni. `s:Un proces multi-thread.

Observăm că Bash are starea `Ss`. `S` majuscul indică faptul că shell-ul Bash este în stare de așteptare întreruptibilă. Iar `s` minuscul ne indică că shell-ul este liderul sesiunii. Comanda `ping` are starea `T`, ceea ce înseamnă că a fost oprită printr-un semnal de control al jobului. În cazul nostru, acesta a fost Ctrl+Z.

Comanda `ps T` are starea `R`, ceea ce înseamnă că este în execuție. Semnul `+` indică faptul că acest proces este membru al grupului din prim-plan, deci `ps T` rulează în prim-plan.

Comanda bg

Comanda `bg` este utilizată pentru a relua un proces din fundal, cu sau fără numărul jobului. Dacă nu este specificat niciun număr, se va relua jobul implicit. Reține că procesul rulează în continuare în fundal, fără a putea primi nicio intrare.

Să reluăm comanda `ping` folosind comanda `bg`:

bg

Comanda `ping` se reia, și observăm afișarea continuă a rezultatelor în terminal. Numele comenzii repornite este afișat (marcat în imagine).

Avem o problemă: comanda rulează în fundal și nu acceptă nicio comandă. Ctrl+C nu are niciun efect. Putem tasta comenzi, dar acestea sunt rapid acoperite de output-ul comenzii `ping`. Orice introducem intră în vigoare în prim plan.

Pentru a opri comanda din fundal, trebuie să o aducem în prim-plan și apoi să o oprim.

Comanda fg

Comanda `fg` aduce un job din fundal în prim-plan, utilizată cu sau fără numărul jobului. Dacă este utilizată cu un număr specific, se aplică acelui job; altfel, se aplică ultimului job trimis în fundal.

Dacă tastăm `fg`, comanda `ping` va reveni în prim-plan. Caracterele pe care le introducem se amestecă cu output-ul comenzii `ping`, dar vor fi procesate ca și cum le-am tasta în mod normal, la linia de comandă. Pentru shell, asta s-a și întâmplat.

fg

Acum că am adus comanda `ping` în prim-plan, putem folosi Ctrl+C pentru a o opri.

Ctrl+C

Semnalele Corecte

Nu a fost chiar un mod ideal de a lucra. Este clar că rularea unui proces în fundal este mai utilă când acesta nu produce output sau nu necesită input.

Dar exemplul nostru a ilustrat cu succes:

  • Punerea unui proces în fundal.
  • Reluarea unui proces în fundal.
  • Revenirea procesului în prim-plan.
  • Oprirea procesului.

Când folosim Ctrl+C și Ctrl+Z, transmitem semnale proceselor. Acestea sunt metode rapide de a utiliza comanda `kill`. Există 64 de semnale diferite pe care comanda `kill` le poate trimite. Pentru a vedea lista, folosește `kill -l` în terminal. Aceste semnale nu provin doar de la comanda `kill`, unele sunt generate automat de către sistem.

Iată câteva dintre semnalele cel mai des utilizate:

  • `SIGHUP`: Semnalul 1. Trimis automat unui proces când terminalul în care rulează este închis.
  • `SIGINT`: Semnalul 2. Trimis unui proces când apasă Ctrl+C. Procesul este întrerupt și i se spune să se încheie.
  • `SIGQUIT`: Semnalul 3. Trimis unui proces când utilizatorul trimite un semnal de ieșire Ctrl+D.
  • `SIGKILL`: Semnalul 9. Procesul este oprit imediat, fără a încerca o închidere controlată. Procesul se închide brusc.
  • `SIGTERM`: Semnalul 15. Semnalul implicit trimis de `kill`. Este un semnal standard pentru a închide un program.
  • `SIGTSTP`: Semnalul 20. Trimis unui proces când se apasă Ctrl+Z. Oprește procesul și îl trimite în fundal.

Comanda `kill` este necesară pentru a emite semnale care nu au alocate combinații de taste.

Control Suplimentar al Joburilor

Un proces mutat în fundal prin Ctrl+Z este oprit. Trebuie să folosim `bg` pentru a-l relua. Pentru a porni un program ca proces de fundal, adaugă `&` la finalul comenzii.

Deși ideal procesele din fundal nu ar trebui să scrie în terminal, vom folosi exemple care o fac, pentru a ilustra rezultatele. Comanda de mai jos va porni o buclă infinită în fundal:

`while true; do echo „Procesul buclei Geek”; sleep 3; done &`

Terminalul afișează numărul jobului și ID-ul procesului. În acest caz, numărul jobului este `1`, iar ID-ul procesului este `1979`. Aceste valori ne vor ajuta să controlăm procesul.

Output-ul buclei începe să apară în terminal. Similar cu situațiile anterioare, putem folosi linia de comandă, dar comenzile pe care le tastăm sunt amestecate cu output-ul buclei.

ls

Pentru a opri procesul, putem folosi comanda `jobs` pentru a ne reaminti numărul jobului, apoi folosim `kill`.

`jobs` ne raportează că procesul este jobul `1`. Pentru a utiliza acest număr cu `kill`, trebuie să îl precedăm cu simbolul `%`.

jobs
kill %1

`kill` trimite semnalul `SIGTERM` (semnalul 15) procesului, care apoi se încheie. După ce apăsăm tasta Enter, este afișată starea jobului, care indică faptul că procesul s-a încheiat. Dacă procesul nu răspunde la comanda `kill`, poți folosi `kill` cu `SIGKILL`, adică semnalul `9`: `kill 9 %1`.

Rezumatul Comenzilor

Iată un rezumat al comenzilor discutate:

Ctrl+C Trimite `SIGINT` (semnal 2) procesului, dacă acceptă intrare, și îi cere să se termine.
Ctrl+D Trimite `SIGQUIT` (semnal 3) procesului, dacă acceptă intrare, și îi cere să se încheie.
Ctrl+Z Trimite `SIGSTP` (semnal 20) procesului și îl oprește, transformându-l într-un proces de fundal.
jobs Listează joburile din fundal și numărul acestora.
bg job_number Repornește un proces din fundal. Dacă nu se specifică un număr, se folosește ultimul proces transformat într-un job de fundal.
fg job_number Aduce un proces din fundal în prim-plan și îl repornește. Dacă nu se specifică un număr, se folosește ultimul proces transformat într-un job de fundal.
comandă & Execută comanda în fundal.
kill %job_number Trimite `SIGTERM` (semnal 15) procesului pentru a-l încheia.
kill 9 %job_number Trimite `SIGKILL` (semnal 9) procesului și îl încheie brusc.