O parte importantă a învățării de a lucra cu Ubuntu, și cu distribuțiile Linux în general, implică dobândirea competenței de a lucra în mediul shell. În timp ce mediile desktop grafice, cum ar fi GNOME, incluse în Linux, oferă o interfață prietenoasă cu sistemul de operare, în practică, mediul shell oferă capacități, flexibilitate și automatizare mult mai mari decât cele care pot fi obținute vreodată cu ajutorul instrumentelor desktop grafice. Mediul shell oferă, de asemenea, un mijloc de interacțiune cu sistemul de operare atunci când nu este disponibil un mediu desktop; o situație frecventă atunci când se lucrează cu un sistem de operare bazat pe server, cum ar fi Ubuntu, sau cu un sistem deteriorat care nu pornește complet.
Obiectivul acestui capitol, prin urmare, este de a oferi o prezentare generală a mediului shell implicit pe Ubuntu (în special a shell-ului Bash).
1.1 Ce este un shell?
Shell-ul este un mediu interactiv de interpretare a comenzilor în cadrul căruia comenzile pot fi tastate la un prompt sau introduse într-un fișier sub forma unui script și executate. Originile shell-ului pot fi urmărite încă din primele zile ale sistemului de operare UNIX. De fapt, în primele zile ale Linux, înainte de introducerea desktopurilor grafice, shell-ul era singura modalitate prin care un utilizator putea interacționa cu sistemul de operare.
A lungul anilor au fost dezvoltate o varietate de medii shell. Primul shell utilizat pe scară largă a fost shell-ul Bourne, scris de Stephen Bourne la Bell Labs.
O altă creație timpurie a fost shell-ul C, care a împărtășit unele asemănări de sintaxă cu limbajul de programare C și a introdus îmbunătățiri de utilizare, cum ar fi editarea liniei de comandă și istoricul.
Chell-ul Korn (dezvoltat de David Korn la Bell Labs) se bazează pe caracteristicile oferite atât de shell-ul Bourne cât și de shell-ul C.
Chell-ul implicit pe Ubuntu este shell-ul Bash (prescurtare de la Bourne Again SHell). Acest shell, care și-a început viața ca o versiune open source a shell-ului Bourne, a fost dezvoltat pentru proiectul GNU de către Brian Fox și se bazează pe caracteristici furnizate atât de shell-ul Bourne, cât și de shell-ul C.
1.2 Obținerea accesului la shell
Din mediul desktop GNOME, promptul shell poate fi accesat dintr-o fereastră Terminal selectând opțiunea Activities din bara de sus, introducând Terminal în bara de căutare și făcând clic pe pictograma Terminal.
Când se conectează de la distanță la un server Ubuntu, de exemplu, folosind SSH, utilizatorului i se prezintă, de asemenea, un prompt shell. Detaliile privind accesarea unui server de la distanță utilizând SSH vor fi tratate în capitolul intitulat „Configurarea autentificării bazate pe cheia SSH pe Ubuntu”. La pornirea unui sistem bazat pe server în care nu a fost instalat un mediu desktop, shell-ul este introdus imediat după ce utilizatorul finalizează procedura de conectare la terminalul de consolă fizică sau la sesiunea de conectare de la distanță.
1.3 Introducerea comenzilor la prompt
Comenzile sunt introduse la promptul de comenzi shell prin simpla tastare a comenzii și apăsarea tastei Enter. În timp ce unele comenzi execută sarcini în mod silențios, majoritatea vor afișa o anumită formă de ieșire înainte de a reveni la prompt. De exemplu, comanda ls poate fi utilizată pentru a afișa fișierele și directoarele din directorul de lucru curent:
$ ls
Desktop Documents Downloads Music Pictures Public Templates Videos
Comenzile disponibile sunt fie încorporate în shell-ul însuși, fie rezidă în sistemul de fișiere fizic. Locația pe sistemul de fișiere a unei comenzi poate fi identificată cu ajutorul comenzii which. De exemplu, pentru a afla unde locuiește executabilul ls pe sistemul de fișiere:
$ which ls alias ls='ls --color=auto' /usr/bin/ls
Evident, comanda ls locuiește în directorul /usr/bin. Observați, de asemenea, că este configurat un alias, un subiect care va fi abordat mai târziu în acest capitol. Utilizarea comenzii which pentru a localiza calea de acces la comenzile care sunt încorporate în shell va avea ca rezultat un mesaj care indică faptul că executabilul nu poate fi găsit. De exemplu, încercarea de a găsi locația comenzii history (care este de fapt încorporată în shell mai degrabă decât să existe ca executabil pe sistemul de fișiere) va avea ca rezultat o ieșire similară cu următoarea:
$ which history/usr/bin/which: no history in (/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)
1.4 Obținerea de informații despre o comandă
Multe dintre comenzile disponibile în shell-ul Linux pot părea enigmatice la început. Pentru a afla informații detaliate despre ce face o comandă și cum să o utilizați, folosiți comanda man specificând ca argument numele comenzii. De exemplu, pentru a afla mai multe despre comanda pwd:
$ man pwd
Când se execută comanda de mai sus, se va afișa o descriere detaliată a comenzii pwd. Multe comenzi vor oferi, de asemenea, informații suplimentare atunci când sunt executate cu opțiunea de linie de comandă -help:
$ wc --help
1.5 Editarea liniei de comandă Bash
Mediile shell timpurii nu ofereau nici o formă de capacități de editare a liniilor. Acest lucru însemna că, dacă depistați o eroare la începutul unei linii de comandă lungi pe care o tastați, trebuia să ștergeți toate caracterele următoare, să corectați eroarea și apoi să introduceți din nou restul comenzii. Din fericire, Bash oferă o gamă largă de opțiuni de editare a liniei de comandă, așa cum se arată în tabelul următor:
Secvență de taste | Acțiune |
Ctrl-b sau săgeată spre stânga | Mutarea cursorului înapoi cu o poziție |
Ctrl…f sau Săgeată dreapta | Mutați cursorul înainte o poziție |
Delete | Ștergeți caracterul curent sub cursor |
Backspace | Șterge caracterul din stânga cursorului |
Ctrl-_ | Undo previous change (poate fi repetat pentru a anula toate modificările anterioare) |
Ctrl-a | Mutați cursorul la începutul liniei |
Ctrl-e | Mutați cursorul la sfârșitul liniei |
Meta-.f sau Esc apoi f | Mutați cursorul înainte cu un cuvânt |
Meta-b sau Esc apoi b | Mutați cursorul înapoi cu un cuvânt |
Ctrl-.l | Curățați ecranul de tot, cu excepția comenzii curente |
Ctrl-k | Șterge până la sfârșitul liniei de la poziția curentă a cursorului |
Meta-d sau Esc apoi d | Ștergere până la sfârșitul cuvântului curent |
Meta-DEL sau Esc apoi DEL | Ștergere de la începutul cuvântului curent |
Ctrl-w | Delete de la poziția curentă a cursorului până la spațiul alb anterior |
Tabelul 9-1
1.6 Lucrul cu istoricul shell-ului
În plus față de caracteristicile de editare a liniei de comandă, shell-ul Bash oferă, de asemenea, suport pentru istoricul liniei de comandă. O listă de comenzi executate anterior poate fi vizualizată cu ajutorul comenzii history:
$ history1ps2ls3ls –l /4ls5man pwd6man apropos
În plus, Ctrl-p (sau săgeata sus) și Ctrl-n (sau săgeata jos) pot fi folosite pentru a derula înainte și înapoi prin comenzile introduse anterior. Când comanda dorită din istoric este afișată, apăsați tasta Enter pentru a o executa.
O altă opțiune este introducerea caracterului ‘!’ urmat de primele câteva caractere ale comenzii care trebuie repetată, urmată de tasta Enter.
1.7 Prescurtarea numelui de fișier
Multe comenzi de shell iau ca argumente unul sau mai multe nume de fișiere. De exemplu, pentru a afișa conținutul unui fișier text numit list.txt, comanda cat ar fi utilizată după cum urmează:
$ cat list.txt
În mod similar, conținutul mai multor fișiere text ar putea fi afișat prin specificarea tuturor numelor de fișiere ca argumente:
$ cat list.txt list2.txt list3.txt list4.txt
În loc să se tasteze fiecare nume, se poate utiliza potrivirea de tipare pentru a specifica toate fișierele cu nume care corespund anumitor criterii. De exemplu, caracterul wildcard ‘*’ poate fi utilizat pentru a simplifica exemplul de mai sus:
$ cat *.txt
Comanda de mai sus va afișa conținutul tuturor fișierelor care se termină cu extensia .txt. Aceasta ar putea fi restrânsă și mai mult la orice nume de fișier care începe cu list și se termină cu .txt:
$ cat list*.txt
Se pot specifica potriviri cu un singur caracter folosind caracterul „?”:
$ cat list?.txt
1.8 Completarea numelui de fișier și a căii de acces
În loc să se tasteze un nume de fișier sau o cale de acces întreagă, sau să se folosească potrivirea de tipare pentru a reduce cantitatea de tastare, shell-ul oferă funcția de completare a numelui de fișier. Pentru a utiliza funcția de completare a numelui de fișier, este suficient să introduceți primele câteva caractere ale numelui fișierului sau ale căii de acces și apoi să apăsați de două ori tasta Esc. În acest caz, shell-ul va completa numele fișierului pentru dumneavoastră cu primul nume de fișier sau de cale din director care corespunde caracterelor introduse. Pentru a obține o listă a posibilelor potriviri, apăsați Esc = după introducerea primelor câteva caractere.
1.9 Redirecționarea intrărilor și ieșirilor
După cum s-a menționat anterior, multe comenzi de tip shell scot informații atunci când sunt executate. În mod implicit, această ieșire merge către un fișier de dispozitiv numit stdout, care este în esență fereastra terminalului sau consola în care rulează shell-ul. Invers, shell-ul primește intrări de la un fișier de dispozitiv numit stdin, care, în mod implicit, este tastatura.
Ieșirea unei comenzi poate fi redirecționată de la stdout la un fișier fizic din sistemul de fișiere folosind caracterul ‘>’. De exemplu, pentru a redirecționa ieșirea de la o comandă ls către un fișier numit files.txt, ar fi necesară următoarea comandă:
$ ls *.txt > files.txt
La finalizare, files.txt va conține lista fișierelor din directorul curent. În mod similar, conținutul unui fișier poate fi introdus într-o comandă în loc de stdin. De exemplu, pentru a redirecționa conținutul unui fișier ca intrare a unei comenzi:
$ wc –l < files.txt
Comanda de mai sus va afișa numărul de linii conținute în fișierul files.txt.
Este important de reținut că operatorul de redirecționare „>” creează un fișier nou sau trunchiază un fișier existent atunci când este utilizat. Pentru a adăuga la un fișier existent, utilizați operatorul ‘>>’:
$ ls *.dat >> files.txt
În plus față de ieșirea standard, shell-ul oferă, de asemenea, ieșire de eroare standard utilizând stderr. În timp ce ieșirea de la o comandă este direcționată către stdout, orice mesaj de eroare generat de comandă este direcționat către stderr. Acest lucru înseamnă că, dacă stdout este direcționat către un fișier, mesajele de eroare vor apărea în continuare în terminal. Acesta este, în general, comportamentul dorit, deși stderr poate fi, de asemenea, redirecționat, dacă se dorește, folosind operatorul ‘2>’:
$ ls dkjfnvkjdnf 2> errormsg
La finalizarea comenzii, o eroare care raportează faptul că fișierul numit dkjfnvkjjdnf nu a putut fi găsit va fi conținută în fișierul errormsg.
Atât stderr cât și stdout pot fi redirecționate către același fișier folosind operatorul &>:
$ ls /etc dkjfnvkjdnf &> alloutput
La terminarea execuției, fișierul alloutput va conține atât o listă a conținutului directorului /etc, cât și mesajul de eroare asociat cu încercarea de a lista un fișier inexistent.
1.10 Lucrul cu țevi în shell-ul Bash
În plus față de redirecționarea I/O, shell-ul permite, de asemenea, ca ieșirea de la o comandă să fie dirijată direct ca intrare pentru o altă comandă. O operațiune pipe se realizează prin plasarea caracterului „|” între două sau mai multe comenzi pe o linie de comandă. De exemplu, pentru a număra numărul de procese care rulează pe un sistem, ieșirea de la comanda ps poate fi direcționată către comanda wc:
$ ps –ef | wc –l
Nu există o limită a numărului de operații pipe care pot fi efectuate pe o linie de comandă. De exemplu, pentru a afla numărul de linii dintr-un fișier care conțin numele Smith:
$ cat namesfile | grep Smith | wc –l
1.11 Configurarea Aliasurilor
Pe măsură ce dobândiți competență cu mediul shell este probabil să vă treziți că veți emite frecvent comenzi cu aceleași argumente. De exemplu, este posibil să folosiți adesea comanda ls cu opțiunile l și t:
$ ls –lt
Pentru a reduce cantitatea de tastare implicată în emiterea unei comenzi, este posibil să creați un alias care să corespundă comenzii și argumentelor. De exemplu, pentru a crea un alias astfel încât introducerea literei l să determine executarea comenzii ls -lt, se va utiliza următoarea instrucțiune:
$ alias l="ls –lt"
Introducerea literei l la promptul de comandă va executa acum instrucțiunea originală.
1.12 Variabile de mediu
Variabilele de mediu ale shell-ului asigură stocarea temporară a datelor și a setărilor de configurare. Shell-ul însuși stabilește un număr de variabile de mediu care pot fi schimbate de către utilizator pentru a modifica comportamentul shell-ului. O listă a variabilelor definite în prezent poate fi obținută cu ajutorul comenzii env:
$ envSSH_CONNECTION=192.168.0.19 61231 192.168.0.28 22MODULES_RUN_QUARANTINE=LD_LIBRARY_PATHLANG=en_US.UTF-8HISTCONTROL=ignoredupsHOSTNAME=demo-pc.ebookfrenzy.comXDG_SESSION_ID=15MODULES_CMD=/usr/share/Modules/libexec/modulecmd.tclUSER=demoENV=/usr/share/Modules/init/profile.shSELINUX_ROLE_REQUESTED=PWD=/home/demoHOME=/home/demoSSH_CLIENT=192.168.0.19 61231 22SELINUX_LEVEL_REQUESTED= ...
Poate cea mai utilă variabilă de mediu este PATH. Aceasta definește directoarele în care shell-ul va căuta comenzile introduse la promptul de comandă, precum și ordinea în care va face acest lucru. Variabila de mediu PATH pentru un cont de utilizator pe un sistem Ubuntu nou instalat va fi probabil configurată după cum urmează:
$ echo $PATH/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/ bin:/usr/local/sbin:/usr/sbin
O altă variabilă utilă este HOME, care specifică directorul de domiciliu al utilizatorului curent. Dacă, de exemplu, ați dori ca shell-ul să caute comenzi și în directorul de scripturi aflat în directorul dvs. personal, ați modifica variabila PATH după cum urmează:
$ export PATH=$PATH:$HOME/scripts
Valoarea curentă a unei variabile de mediu existente poate fi afișată cu ajutorul comenzii echo:
$ echo $PATH
Vă puteți crea propriile variabile de mediu cu ajutorul comenzii export. De exemplu:
$ export DATAPATH=/data/files
Un truc util pentru a atribui rezultatul unei comenzi unei variabile de mediu implică utilizarea ghilimelelor (`) în jurul comenzii. De exemplu, pentru a atribui data și ora curentă unei variabile de mediu numită NOW:
$ export NOW=`date`$ echo $NOWTue Apr 2 13:48:40 EDT 2020
Dacă există setări ale variabilelor de mediu sau ale aliasurilor de care aveți nevoie pentru a fi configurate de fiecare dată când intrați în mediul shell, acestea pot fi adăugate la un fișier din directorul dvs. personal numit .bashrc. De exemplu, următorul fișier .bashrc este configurat pentru a seta variabila de mediu DATAPATH și un alias:
# .bashrc # Source global definitionsif ; then . /etc/bashrcfi # User specific environmentPATH="$HOME/.local/bin:$HOME/bin:$PATH"export PATH # Uncomment the following line if you don't like systemctl's auto-paging feature:# export SYSTEMD_PAGER= # User specific aliases and functionsexport DATAPATH=/data/filesalias l="ls -lt"
1.13 Scrierea de scripturi de shell
Până acum ne-am concentrat exclusiv pe natura interactivă a shell-ului Bash. Prin interactiv înțelegem introducerea manuală a comenzilor la prompt, una câte una, și executarea lor. De fapt, aceasta este doar o mică parte din ceea ce este capabil să facă shell-ul. Se poate spune că unul dintre cele mai puternice aspecte ale shell-ului implică abilitatea de a crea scripturi shell. Scripturile shell sunt, în esență, fișiere text care conțin secvențe de instrucțiuni care pot fi executate în mediul shell pentru a efectua sarcini. În plus față de capacitatea de a executa comenzi, shell-ul oferă multe dintre construcțiile de programare, cum ar fi buclele for și do și instrucțiunile if, pe care vă puteți aștepta în mod rezonabil să le găsiți într-un limbaj de scripting.
Din păcate, o prezentare detaliată a scripting-ului shell depășește scopul acestui capitol. Cu toate acestea, există multe cărți și resurse web dedicate scripturilor shell care fac subiectului mult mai multă dreptate decât am putea spera să realizăm aici. În această secțiune, prin urmare, vom oferi doar o foarte mică mostră de scripting shell.
Primul pas în crearea unui script shell este crearea unui fișier (în scopul acestui exemplu îl vom numi simplu.sh) și să adăugăm următoarele ca primă linie:
#!/bin/sh
Numele #! se numește „shebang” și este o secvență specială de caractere care indică faptul că calea către interpretorul necesar pentru a executa scriptul este următorul element de pe linie (în acest caz executabilul sh situat în /bin). Aceasta ar putea fi în egală măsură, de exemplu, /bin/csh sau /bin/ksh, dacă oricare dintre acestea ar fi interpretorul pe care doriți să îl utilizați.
Postul următor este să scrieți un script simplu:
#!/bin/shfor i in *do echo $idone
Tot ce face acest script este să parcurgă toate fișierele din directorul curent și să afișeze numele fiecărui fișier. Acesta poate fi executat trecând numele scriptului ca argument pentru sh:
$ sh simple.sh
Pentru a face fișierul executabil (eliminând astfel necesitatea de a-l trece prin comanda sh) se poate folosi comanda chmod:
$ chmod +x simple.sh
După ce bitul execute a fost setat pe permisiunile fișierului, acesta poate fi executat direct. De exemplu:
$ ./simple.sh
1.14 Rezumat
În acest capitol din Ubuntu Essentials am făcut un scurt tur al mediului shell Bash. În lumea mediilor desktop grafice este ușor să uităm că adevărata putere și flexibilitate a unui sistem de operare poate fi adesea utilizată doar prin coborârea sub interfața prietenoasă a desktop-ului și utilizarea unui mediu shell. Mai mult decât atât, familiarizarea cu shell-ul este o necesitate atunci când este necesar să se administreze și să se întrețină sisteme bazate pe server care nu au instalat desktop-ul sau atunci când se încearcă repararea unui sistem care este deteriorat până la punctul în care interfața desktop sau Cockpit nu se mai lansează.
.