Atunci când rulăm o comandă aceasta își poate încheia execuția în două moduri: cu succes sau cu eșec. Atunci când își încheie execuția, orice proces întoarce un cod de eroare, care este un număr:
0
, procesul și-a încheiat execuția cu succes.man
a utilitarului ls
este specificat:Exit status: 0 if OK, 1 if minor problems (e.g., cannot access subdirectory), 2 if serious trouble (e.g., cannot access command-line argument).
Pentru a vedea codul cu care și-a încheiat execuția o comandă folosim sintaxa $?
. Urmărim exemplul de mai jos:
student@uso:~$ ls Desktop/ todos.txt student@uso:~$ echo $? 0 student@uso:~$ ls non-existent ls: cannot access 'non-existent': No such file or directory student@uso:~$ echo $? 2
Observăm că în cazul fișierului inexistet, comanda ls non-existent
a întors valoarea 2
, așa cum era specificat și în pagina de manual.
De multe ori vrem să executăm o succesiune de comenzi pentru a realiza o sarcină. De exemplu, atunci când vrem să instalăm o aplicație o rulăm trei comenzi:
apt update
apt install
Preferăm să înlănțuim cele trei comenzi într-una singură pentru că astfel putem să pornim tot acest proces, să plecăm de la calculator, iar când ne întoarcem avem tot sistemul pregătit.
Pentru a înlănțui comenzi în terminalul bash avem trei operatori disponibili:
;
care este folosit pentru separarea comenzilor. Urmăm exemplul de mai jos:student@uso:~$ mkdir demo; cd demo; touch Hello; ls Hello
În exemplul de mai sus am creat directorul demo
, am navigat în interiorul său, am creat fișierul Hello
și am afișat conținutul directorului. Am făcut toate acestea înlănțuind comenzile mkdir
, cd
, touch
și ls
cu ajutorul operatorului ;
.
Operatorul ;
este folosit pentru separarea comenzilor, dar nu ține cont dacă comenzile anterioare au fost executate cu succes sau nu. Urmăm exemplul de mai jos:
student@uso:~$ mkdir operators/demo; cd operators/demo mkdir: cannot create directory ‘operators/demo’: No such file or directory -bash: cd: operators/demo: No such file or directory
În exemplul de mai sus, comanda mkdir
a eșuat deoarece nu a găsit directorul operators
în care să creeze directorul demo
. Cu toate acestea, operatorul ;
doar separă comenzile între ele, așa că și comanda cd operators/demo
a fost executată, și și aceasta a eșuat deoarece nu există calea operators/demo
.
Folosim operatorul ;
pentru a înlănțui comenzi care sunt independente unele de altele, și deci execuția lor nu depinde de succesul unei comenzi precedente.
&&
(și logic) - execută a doua comandă doar dacă precedenta s-a executat cu succes. Exemplul anterior devine:student@uso:~$ mkdir operators/demo && cd operators/demo mkdir: cannot create directory ‘operators/demo’: No such file or directory
Observăm că din moment ce comanda mkdir
a eșuat, comanda cd
nu a mai fost executată.
||
(sau logic) - execută a doua comandă doar dacă prima s-a terminat cu eșec. Urmărim exemplul de mai jos:student@uso:~$ (ls -d operators || mkdir operators) && ls -d operators ls: cannot access 'operators': No such file or directory operators student@uso:~$ (ls -d operators || mkdir operators) && ls -d operators operators operators
În exemplul de mai sus, prima comandă ls
a eșuat, așa că a fost executată comanda mkdir
și apoi a fost executată ultima comandă ls
. La cea de-a doua rulare, a fost executată cu succes prima comandă ls
, așa că comanda mkdir
nu a mai fost executată, și apoi a fost executată ultima comandă ls
.
Pentru a rezolva scenariul de la care am plecat inițial, putem rula:
sudo apt update && sudo apt install -y cowsay && cowsay "Howdy"
Comanda de mai sus va actualiza indexul pachetelor sursă, va instala pachetul cowsay
și va rula comanda cowsay
pentru a valida instalarea. O astfel de înlănțuire de comenzi este numită oneliner.
~/uso-lab/labs/05-cli/support/make-folder
și apoi copiați conținutul directorului ~~/uso-lab/labs/05-cli/support/redir
în el.make all
.
Așa cum am descoperit în secțiunile și capitolele anterioare, în mediul Linux avem multe utilitare care rezolvă o nevoie specifică: ls
afișează informații despre fișiere, ps
despre procese, grep
filtrează, etc. Toate acestea au la bază filozofia mediului Linux: “do one thing and do it well”. Ca întodeauna, frumusețea stă în simplitate: avem o suită de unelte la dispoziție, fiecare capabilă să rezolve rapid o sarcină dată; pentru a rezolva o problemă mai complexă trebuie doar să îmbinăm uneltele.
Operatorul |
(pipe) ne ajută să facem acest lucru. Atunci când folosim operatorul |
preluăm rezultatul comenzii din stânga operatorului și îl oferim ca intrare comenzii aflate în dreapta operatorului.
Am folosit de mai multe ori operatorul |
până acum:
student@uso:~$ ps -e | grep firefox 14912 pts/0 00:00:19 firefox
student@uso:~$ ps -e -ouser,uid,pid,%mem,%cpu,rss,cmd --sort=-%mem | head -11 USER UID PID %MEM %CPU RSS CMD student 1000 7938 18.0 0.1 367952 /usr/bin/gnome-shell student 1000 8437 8.4 0.0 171916 /usr/bin/gnome-software --gapplication-service student 1000 7782 3.9 0.0 81312 /usr/lib/xorg/Xorg vt1 -displayfd 3 -auth /run/user/1000/gdm/Xauthority -background none -noreset -keeptty -verbose 3 root 0 1338 3.8 0.0 78880 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock student 1000 8307 3.1 0.0 64628 /usr/lib/evolution/evolution-calendar-factory student 1000 8338 3.0 0.0 61860 /usr/lib/evolution/evolution-calendar-factory-subprocess --factory all --bus-name org.gnome.evolution.dataserver.Subprocess.Backend.Calendarx8307x2 --own-path /org/gnome/evolution/dataserver/Subprocess/Backend/Calendar/8307/2 root 0 336 2.6 0.0 53612 /lib/systemd/systemd-journald student 1000 8274 2.3 0.0 48296 nautilus-desktop root 0 1074 2.2 0.0 45460 /usr/bin/containerd student 1000 12966 1.8 0.0 38216 /usr/lib/gnome-terminal/gnome-terminal-server
Ne amintim de fișierul /etc/passwd
conține informații despre toți utilizatorii din sistem.
student@uso:~$ cat /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin (...)
În Linux există filtrul de text cut
prin care putem extrage doar anumite informații dintr-un output.
Să zicem că vrem să extragem doar numele utilizatorilor, fără informațiile legate de grupuri sau home directory.
student@uso:~/uso-lab$ cat /etc/passwd | cut -f1 -d":" root daemon bin (...)
Argumentul -f1
specifică faptul că vrem prima coloană, iar argumentul -d:
specifică delimitatorul
de coloane, în cazul nostru :
.
man sort
)wc
, obțineți numărul de utilizatori din sistem. (Hint: man wc
)|
și tail
)Majoritatea utilitarelor pe care le folosim afișează rezultatele operațiilor pe care le aplică la ieșirea standard, adică pe ecran. În continuare vom aprofunda ceea ce am discutat despre redirectări în capitolul Lucrul cu Fișiere. Anterior am mai menționat și termenul de intrare standard; în această secțiune ne vom clarifica ce înseamnă, ce rol îndeplinesc și cum ne folosim de aceste cunoștințe. Acum, adăugăm câteva informații noi la ceea ce am învățat deja.
Putem folosi niște fișiere speciale pentru redirectarea outputulu sau erorilor sau din care să citim input. Detaliem mai jos.
Pe sistemele Linux găsim un număr de fișiere speciale pe care le putem folosim în diferite scopuri:
Fișierul /dev/null
este un fișier care ignoră orice este scris în el. Este echivalentul unei găuri negre în sistemul nostru. Cu ajutorul său, putem rescrie exemplul de mai sus în modul următor:
student@uso:~$ firefox &> /dev/null & [1] 10349 student@uso:~$ firefox > /dev/null 2>&1 & [2] 10595
Acum orice va genera firefox
va fi scris în /dev/null
, care va consuma textul primit fără a ocupa spațiu pe disc.
Fișierul /dev/zero
este un generator de octeți. Acesta generează atâția octeți cu valoarea zero (0)1) cât îi sunt ceruți. Urmăm exemplul:
student@uso:~$ cat /dev/zero | xxd 00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................ [...] ^C
Deoarece citim din generator, comanda cat
va afișa o infinitate de octeți cu valoarea zero. Utilitarul xxd
afișează în hexazecimal textul primit la STDIN. Trecem rezultatul lui cat
prin xxd
deoarece valoarea 0 nu este un caracter printabil. Cu alte cuvinte nu este un caracter obișnuit, ca cele de pe tastatură, deoarece nu are un echivalent grafic. Folosim Ctrl+c
pentru a opri execția.Exercițiu: Rulați comanda cat /dev/zero
pentru a înțelege nevoia utilitarului xxd
din exemplul de mai sus.
/dev/urandom
este un alt generator de octeți pe care-l putem folosi pentru extragerea de caractere. De exemplu, pentru a genera o parola de 30 de caractere alfanumerice.
/dev/urandom
.
Generatoarele de octeți sunt utile pentru a testa aplicațiile pe care le dezvoltăm. Majoritatea aplicațiilor pe care le vom scrie, ca și cele pe care le utilizăm, citesc și prelucrează informații. Testăm o aplicație pentru că vrem să verificăm că nu avem buguri. Pentru aceasta putem să folosim seturi de date de intrare cât mai variate și mai aleatoare, adică inputuri random. Folosim utilitarul dd
pentru a genera un fișier de 100 MB cu octeți random, ca în exemplul de mai jos:
student@uso:~$ dd if=/dev/urandom of=rand-100mb count=100 bs=1M 100+0 records in 100+0 records out 104857600 bytes (105 MB, 100 MiB) copied, 1,11416 s, 94,1 MB/s student@uso:~$ ls -lh rand-100mb -rw-rw-r-- 1 student student 100M nov 8 17:49 rand-100mb
Am folosit următoarele opțiuni ale utilitarului dd
:
if
- input file - calea către fișierul de unde citimof
- output file - calea către fișierul unde scriembs
- block size - dimensiunea unui block citit din ifcount
- block count - numărul de block-uri cititerand-50mb
folosind utilitarul dd
.
Un caz uzual de utilizare a dd
este suprascrierea unui disc cu informații aleatoare. Această metodă este utilizată ca o formă de securitate atunci când vrem să ștergem informații de pe un disc. Astfel suprascriem datele șterse pentru a preveni posibilitatea recuperării datelor de pe disc. Mai multe informații găsiți aici.
Note de subsol