Atunci când executăm comenzi în terminal, shell-ul creează câte un proces pentru fiecare comandă executată, proces care va fi copilul procesului curent (adică procesul aferent terminalului curent).
student@uso:~/uso-lab$ sleep 100 & [1] 12822 student@uso:~/uso-lab$ ps -o pid,ppid,cmd PID PPID CMD 22346 22345 bash 12822 22346 sleep 100 12823 22346 ps -o pid,ppid,cmd
bash
(proces de tip shell) din lista de mai sus. Acest lucru ne demonstrează faptul că procesul sleep
este un proces separat față de terminalul curent și mai mult, este proces copil al shell-ului.
Să ne reamintim de la laboratorul 2
ce înseamnă comunicarea interprocese. Vrem ca rezultatele primei comenzi (datele de ieșire) să joace
rolul de date de intrare pentru o a doua comandă. Pentru a realiza acest lucru folosim operatorul |
.
student@uso:~/uso-lab$ ls /dev | grep "std" stderr stdin stdout
Aici, outputul comenzii ls
va fi folosit ca intrare pentru grep.
Orice proces care rulează în sistem se poate termina fie cu SUCCES
, fie cu EROARE
. Pentru a verifica
dacă un proces s-a terminat sau nu cu succes, putem inspecta valoarea variabilei speciale $?
.
student@uso:~/uso-lab$ ping -c 1 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=245 ms --- 8.8.8.8 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 245.160/245.160/245.160/0.000 ms [1]+ Done sleep 100 student@uso:~/uso-lab$ echo $? 0
student@uso:~/uso-lab$ ping 192.12.12.1 PING 192.12.12.1 (192.12.12.1) 56(84) bytes of data. ^C --- 192.12.12.1 ping statistics --- 5 packets transmitted, 0 received, 100% packet loss, time 4100ms student@uso:~/uso-lab$ echo $? 1
0
ne spune că procesul s-a terminat cu succes, iar orice altceva reprezintă un
cod de eroare.
În linia de comandă avem posibilitatea de a scrie o singură comandă care să execute, de fapt, mai multe
procese unul după altul, indepenedente unul față de celelalte. Folosim operatorul ;
pentru a înlănțui
2 comenzi.
student@uso:~/uso-lab$ sudo apt-get install sl; ps [sudo] password for student: Reading package lists... Done Building dependency tree Reading state information... Done The following packages were automatically installed and are no longer required: linux-headers-4.15.0-29 linux-headers-4.15.0-29-generic linux-image-4.15.0-29-generic linux-modules-4.15.0-29-generic linux-modules-extra-4.15.0-29-generic Use 'sudo apt autoremove' to remove them. The following NEW packages will be installed: sl 0 upgraded, 1 newly installed, 0 to remove and 211 not upgraded. Need to get 26.4 kB of archives. After this operation, 98.3 kB of additional disk space will be used. Get:1 http://ro.archive.ubuntu.com/ubuntu bionic/universe amd64 sl amd64 3.03-17build2 [26.4 kB] Fetched 26.4 kB in 19s (1393 B/s) perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LC_TIME = "ro_RO.UTF-8", LC_MONETARY = "ro_RO.UTF-8", LC_CTYPE = "UTF-8", LC_COLLATE = "C", LC_ADDRESS = "ro_RO.UTF-8", LC_TELEPHONE = "ro_RO.UTF-8", LC_NAME = "ro_RO.UTF-8", LC_MEASUREMENT = "ro_RO.UTF-8", LC_IDENTIFICATION = "ro_RO.UTF-8", LC_NUMERIC = "ro_RO.UTF-8", LC_PAPER = "ro_RO.UTF-8", LANG = "en_US.UTF-8" are supported and installed on your system. perl: warning: Falling back to a fallback locale ("en_US.UTF-8"). locale: Cannot set LC_CTYPE to default locale: No such file or directory locale: Cannot set LC_ALL to default locale: No such file or directory Selecting previously unselected package sl. (Reading database ... 234220 files and directories currently installed.) Preparing to unpack .../sl_3.03-17build2_amd64.deb ... Unpacking sl (3.03-17build2) ... Setting up sl (3.03-17build2) ... Processing triggers for man-db (2.8.3-2) ... PID TTY TIME CMD 13006 pts/2 00:00:00 ps 22346 pts/2 00:00:00 bash
De multe ori putem avea o situație în care 2 procese depind unul de celălalt. Pentru a realiza acest
lucru folosim operatorul &&
care ne asigură faptul că a doua comandă se va executa doar în cazul în
care prima se execută cu succes.
student@uso:~/uso-lab$ cat my_nonexisting_file.txt && ls cat: my_nonexisting_file.txt: No such file or directory student@uso:~/uso-lab$ echo $? 1
Observăm faptul că fișierul my_nonexisting_file.txt
nu există și faptul că a doua comandă nu se
mai execută, exact ce am dorit să arătăm, codul de eroare 1 arătând că prima comandă nu s-a
terminat cu succes.
Schimbăm puțin abordarea astfel încât ambele comenzi să fie executate.
student@uso:~/uso-lab$ ping -c 1 8.8.8.8 && finger student PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=32.4 ms --- 8.8.8.8 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 32.450/32.450/32.450/0.000 ms Login: student Name: Student User Directory: /home/student Shell: /bin/bash On since Mon Oct 29 21:27 (EET) on :0 from :0 (messages off) On since Mon Oct 29 21:39 (EET) on pts/2 from 192.168.27.1 7 seconds idle No mail. No Plan. student@uso:~/uso-lab$ echo $? 0
Situația opusă pe care o putem întâlni este să vrem să executăm o a doua comandă doar dacă prima nu s-a
terminat cu succes. Pentru a face acest lucru folosim operatorul ||
(sau logic).
student@uso:~/uso-lab$ cat my_nonexisting_file.txt || id root cat: my_nonexisting_file.txt: No such file or directory uid=0(root) gid=0(root) groups=0(root)
În cazul operatorului ||
, a doua comandă nu se va executa dacă prima se termină cu succes.
student@uso:~/uso-lab$ cat /etc/passwd || ls 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 sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin syslog:x:102:106::/home/syslog:/usr/sbin/nologin messagebus:x:103:107::/nonexistent:/usr/sbin/nologin _apt:x:104:65534::/nonexistent:/usr/sbin/nologin uuidd:x:105:111::/run/uuidd:/usr/sbin/nologin avahi-autoipd:x:106:112:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin usbmux:x:107:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin dnsmasq:x:108:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin rtkit:x:109:114:RealtimeKit,,,:/proc:/usr/sbin/nologin cups-pk-helper:x:110:116:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin speech-dispatcher:x:111:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/false whoopsie:x:112:117::/nonexistent:/bin/false kernoops:x:113:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin saned:x:114:119::/var/lib/saned:/usr/sbin/nologin pulse:x:115:120:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin avahi:x:116:122:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin colord:x:117:123:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin hplip:x:118:7:HPLIP system user,,,:/var/run/hplip:/bin/false geoclue:x:119:124::/var/lib/geoclue:/usr/sbin/nologin gnome-initial-setup:x:120:65534::/run/gnome-initial-setup/:/bin/false gdm:x:121:125:Gnome Display Manager:/var/lib/gdm3:/bin/false student:x:1000:1000:Student User,,,:/home/student:/bin/bash vboxadd:x:999:1::/var/run/vboxadd:/bin/false sshd:x:122:65534::/run/sshd:/usr/sbin/nologin festival:x:123:29::/nonexistent:/usr/sbin/nologin test:x:1001:1001::/home/test:/bin/sh test2:x:1002:1002:,,,:/home/test2:/bin/bash
Atunci când folosim operatorii shell putem dori să operăm asupra unei compoziții de comenzi. De exemplu dorim să reținem output-ul a două comenzi într-un fișier. La o rulare precum cea de mai jos nu funcționează:
student@uso:~/uso-lab$ ls ; ps > out 00-intro 02-process 04-appdev 06-hw-boot 08-net 10-sec 01-fs 03-user 05-cli 07-storage 09-vm 11-ctf student@uso:~/uso-lab$ cat out PID TTY TIME CMD 13052 pts/2 00:00:00 ps 22346 pts/2 00:00:00 bash
Observăm că doar rezultatul rulării comenzii ps este redirectat. Pentru a redirecta o înlănțuire de comenzi folosim un subshell, adică vom crea un proces nou shell care va rula cele două comenzi și va transfera rezultatul amândurora în fișier. Un subshell este creat cu ajutorul parantezelor la fel ca mai jos:
student@uso:~/uso-lab$ ( ls ; ps ) > out2 student@uso:~/uso-lab$ cat out2 00-intro 01-fs 02-process 03-user 04-appdev 05-cli 06-hw-boot 07-storage 08-net 09-vm 10-sec 11-ctf out out2 PID TTY TIME CMD 13057 pts/2 00:00:00 bash 13059 pts/2 00:00:00 ps 22346 pts/2 00:00:00 bash
În acest al doilea caz, se vede că ambele rezultate sunt redirecționate în același fișier out2
.
În cazul în care vrem să afișăm toate fișierele ale căror nume încep cu litera a
și au extensia
.txt
, putem folosi globbing
. Simbolul *
este un wildcard și ține locul pentru orice
de oricâte ori.
student@uso:~/uso-lab$ cd ~/uso-lab/05-cli/support/demo/ student@uso:~/.../05-cli/support/demo/$ ls a*.txt a1.txt a3.txt a5.txt a7.txt a9.txt
După ce un shell primește comenzile, parametrii și operatorii de la intrare, și după ce îi separă, realizează operațiile de expandare. Expandarea de acolade înseamnă trecerea prin mai multe opțiuni. De exemplu:
student@uso:~/.../05-cli/support/demo$ ls {2,4,6}.txt 2.txt 4.txt 6.txt
Știm că simbolul ~
ține locul directorului home al utilizatorului curent. Atunci când rulăm
comanda cd ~
, tilda este înlocuită cu valoarea variabilei HOME a shell-ului curent.
student@uso:~/.../05-cli/support/demo$ cd ~ student@uso:~$ pwd /home/student student@uso:~$ echo $HOME /home/student
Expandarea parametrică se referă la construcții care încep cu ${
. Cea mai simplă formă este chiar
expandarea valorii unei variabile:
student@uso:~$ cd uso-lab/ student@uso:~/uso-lab/$ mouse="Jerry" student@uso:~/uso-lab/$ echo ${mouse} Jerry
Comanda de mai sus este echivalentă cu echo $mouse
, însă alcoladele devin utile în momentul în
care vrem să afișăm valoarea unei variabile urmate de un șir.
student@uso:~/uso-lab/$ mouse="Jerry" student@uso:~/uso-lab/$ echo $mouse_the_best student@uso:~/uso-lab/$
Shell-ul va încerca în acest caz să afișeze valoare variabilei mouse_the_best
care, în cazul nostru,
nu există. Pentru a rezolva această problemă, folosim acoladele să specficăm de unde până unde ne referim
la un nume de variabilă.
student@uso:~/uso-lab/$ mouse="Jerry" student@uso:~/uso-lab/$ echo ${mouse}_the_best Jerry_the_best
Un alt caz în care expandarea este utilă este evaluarea expresiilor aritmetice. Pentru început, declarăm 2 variabile în shell:
student@uso:~/uso-lab/$ a=3 student@uso:~/uso-lab/$ b=4 student@uso:~/uso-lab/$ echo $a && echo $b 3 4
Dacă vrem să evaluam valoarea expresiei a+b
, trebuie să folosim următoarea construcție:
student@uso:~/uso-lab/$ echo $((a+b)) 7
echo $a+$b
, shell-ul ar fi înlocuit $a
cu valoarea lui a, adică 3
și $b
cu valoarea lui b, adică 4
, iar rezultatul comenzii ar fi fost șirul de caractere 3+4
,
nu 7
așa cum ne-am fi așteptat.
Pentru a lista toate variabilele de mediu folosite de terminalul curent, folosim comanda env
.
student@uso:~/uso-lab$ env LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36: LC_MEASUREMENT=ro_RO.UTF-8 SSH_CONNECTION=192.168.27.1 49613 192.168.27.217 22 LESSCLOSE=/usr/bin/lesspipe %s %s LC_PAPER=ro_RO.UTF-8 LC_MONETARY=ro_RO.UTF-8 LANG=en_US.UTF-8 S_COLORS=auto LC_NAME=ro_RO.UTF-8 XDG_SESSION_ID=4 USER=student LC_COLLATE=C PROMPT_DIRTRIM=3 PWD=/home/student HOME=/home/student LC_CTYPE=UTF-8 SSH_CLIENT=192.168.27.1 49613 22 XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktop LC_ADDRESS=ro_RO.UTF-8 LC_NUMERIC=ro_RO.UTF-8 SSH_TTY=/dev/pts/2 MAIL=/var/mail/student TERM=xterm-256color SHELL=/bin/bash SHLVL=1 LC_TELEPHONE=ro_RO.UTF-8 LOGNAME=student DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus XDG_RUNTIME_DIR=/run/user/1000 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin LC_IDENTIFICATION=ro_RO.UTF-8 LESSOPEN=| /usr/bin/lesspipe %s LC_TIME=ro_RO.UTF-8 _=/usr/bin/env OLDPWD=/home/student/uso-lab/05-cli/support/demo
O variabilă de mediu foarte importantă și destul de des folosită este variabila de mediu PATH
.
Ea conține mai multe căi în care se caută binarele din sistem, cum ar fi ls
.