Differences

This shows you the differences between two versions of the page.

Link to this comparison view

uso:cursuri:curs-11 [2021/01/18 10:23]
ebru.resul
uso:cursuri:curs-11 [2022/12/20 01:54] (current)
sergiu.weisz
Line 1: Line 1:
 +====== Curs 11 - Automatizarea sarcinilor =======
  
-====== Curs 11 - Administrarea spatiului de stocare ======= +  ​* [[https://docs.google.com/​presentation/d/1c9fhDF-nGlf8w7EwU5s7hb4T-QLzpiXL/edit?​usp=sharing&​ouid=108131427433094834232&​rtpof=true&​sd=true|Slide-uri curs]]
- +
-    ​* [[https://drive.google.com/​file/d/1IVuAlR5BgCFiUYT7KSW80_SXpqOKB_Zh/view?​usp=sharing| Slide-uri curs]] +
-  * [[https://​drive.google.com/​file/​d/​1s1a_YbvwyHzzqR08VLKq92NUlRehHJo5/​view?​usp=sharing| Handout 3on1 and notes space]] +
-  * [[https://​drive.google.com/​file/​d/​1PYZEkWKp06kNfCuLER0nIuhAasV_li7-/​view?​usp=sharing| Handout 6on1]] +
-  * **Cuvinte cheie**: HDD, SSD, Partiționare,​ Formatare, MBR, GPT, RAID, Back-up, LVM, mount, umount+
   * **Suport de curs**   * **Suport de curs**
-    * [[http://elf.cs.pub.ro/uso/res/​carte/​uso_cap-10-storage.pdf ​Capitolul 10 - Administrarea spațiului ​de stocare]]+    * [[https://github.com/​systems-cs-pub-ro/carte-uso/releases ​Utilizarea sistemelor ​de operare]] 
 +        * Secțiunea 13 - Automatizarea sarcinilor
  
-/* +<​HTML>​ 
-  * [[https://drive.google.com/​open?​id=1aN0VW-LvefVPyJKyI_mFjFTlKEjbu8oM|Handouts 3on1 and notes space]] +<​center>​ 
-  * [[https://drive.google.com/open?id=1ilzrwOlni4nnUUgO6g_X_fB6Ktg0sqZD|Handouts 6on1]] +<iframe src="https://docs.google.com/​presentation/d/e/​2PACX-1vRkkdapnVGRS-63NUGpc4uuPSERscZiDp2_jyWIF3qvbG_j5wO9UluTeitc99AjPw/embed?start=false&​loop=false&​delayms=3000"​ frameborder="​0"​ width="​480"​ height="​389"​ allowfullscreen="​true"​ mozallowfullscreen="​true"​ webkitallowfullscreen="​true"></​iframe>​ 
-  * **Cuvinte cheie**: ​+</​center>​ 
 +</​HTML>​
  
-*/+===== Demo-uri ===== 
 + 
 +Pentru rularea demo-urilor de mai jos folosim [[http://​repository.grid.pub.ro/​cs/​uso/​USO%20Demo.ova|mașina virtuală USO Demo]]. Mașina virtuală (în format OVA) poate fi importată în VirtualBox. Comenzile le vom rula în cadrul mașinii virtuale. 
 + 
 +Mașina virtuală deține două interfețe de rețea: 
 +  * ''​eth0''​ pentru accesul la Internet (interfață de tipul NAT) 
 +  * ''​eth1''​ pentru comunicarea cu sistemul fizic (gazdă, //host//) (interfață de tipul //Host-only Adapter//​) 
 + 
 +Pentru a rula demo-ul avem două opțiuni: 
 +  - Folosim direct consola mașinii virtuale. 
 +  - Aflăm adresa IP de pe interfața ''​eth1''​ a mașinii virtuale și ne conectăm prin SSH, de pe sistemul fizic, folosind comanda<​code>​ 
 +ssh student@<​adresa-IP-vm-eth1>​ 
 +</​code>​ unde ''<​adresa-IP-vm-eth1>''​ este adresa IP a interfeței ''​eth1''​ din cadrul mașinii virtuale. 
 + 
 +Pentru conectarea la mașina virtuală folosim numele de utilizator ''​student''​ cu parola ''​student''​. Contul ''​student''​ are permsiuni de ''​sudo''​. Folosind comanda<​code>​ 
 +sudo su - 
 +</​code>​ 
 +obținem permisiuni privilegiate (de ''​root''​) în shell. 
 + 
 +<​note>​ 
 +Dacă dorim să ne conectăm pe SSH iar mașina virtuală nu are adresă IP configurată pe interfața ''​eth1''​ atunci folosim comanda<​code>​ 
 +sudo dhclient eth1 
 +</​code>​ 
 +pentru a obține o adresă IP. 
 +</​note>​ 
 + 
 +<​note>​ 
 +Dacă optăm pentru rularea prin SSH iar sistemul fizic rulează Windows, putem folosi [[http://​www.chiark.greenend.org.uk/​~sgtatham/​putty/​|Putty]] pe post de client SSH pe sistemul fizic. 
 +</​note>​ 
 + 
 +<​note>​ 
 +Comenzile folosite sunt de uz general. Actualizând adresele IP cu adrese potrivite, putem rula cu succes comenzile pe orice sistem sau mașină virtuală Linux. 
 +</​note>​ 
 + 
 +==== Prelucrare note ==== 
 + 
 +Pentru acest scenariu, actualizați [[https://​github.com/​systems-cs-pub-ro/​uso-lab|repository-ul public de USO]] și navigați în subdirectorul ''​lectures/​auto/​grades/'':​ 
 + 
 +<code bash> 
 +student@uso:​~$ cd uso-lab 
 +student@uso:​~/​uso-lab$ git pull 
 +student@uso:​~/​uso-lab$ cd lectures/​auto/​grades 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ls 
 +2016-2017.csv ​ 2017-2018.csv ​ 2018-2019.csv ​ 2019-2020.csv ​ script.wiki ​ show_average_final ​ show_average_final_series ​ show_nums ​ stats.py 
 +</​code>​ 
 + 
 +Directorul conține fișiere CSV (//Comma Separated Values//) reprezentând cataloagele anonimizate de la cursul de USO din ultimii ani: 2016-2017, 2017-2018, 2018-2019, 2019-2020. 
 +Ne propunem să facem prelucrarea acestora. 
 + 
 +Pentru început, să aflăm câți studenți au participat la curs în fiecare an. Folosim utilitarul ''​wc'':​ 
 + 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ wc -l 2016-2017.csv 
 +494 2016-2017.csv 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ wc -l 2017-2018.csv 
 +538 2017-2018.csv 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ wc -l 2018-2019.csv 
 +542 2018-2019.csv 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ wc -l 2019-2020.csv 
 +532 2019-2020.csv 
 +</​code>​ 
 + 
 +Ne dorim o afișare mai aspectuoasă și care să elimine și linia de tip header a fișierului CSV. 
 +Pentru aceasta construim un one-liner:​ 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ tail -n +2 2019-2020.csv | wc -l 
 +531 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ echo -n "​2019-2020:​ " ; tail -n +2 2019-2020.csv | wc -l 
 +2019-2020: 531 
 +</​code>​ 
 +Am folosit utilitarul ''​tail''​ ca să eliminăm din afișare headerul fișierului. 
 +Am folosit operatorul pipe (''​|''​) ca să filtrăm apoi rezultatul prin utilitarul ''​wc''​. 
 + 
 +Am putea rula o comandă precum cea de mai sus pentru toate cele patru fișiere. 
 +Dar ar trebui să modificăm pe rând fiecare an universitar. 
 +Vrem o variantă mai eficientă, care să permită inclusiv "​scalarea"​ la apariția unor fișiere pentru alți ani. 
 +Pentru aceasta construim un nou one-liner care să folosească ''​for''​ pentru a parcurge fișierele CSV: 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ for i in *.csv; do echo -n "​$(basename "​$i"​ .csv): " ; tail -n +2 "​$i"​ | wc -l; done 
 +2016-2017: 493 
 +2017-2018: 537 
 +2018-2019: 541 
 +2019-2020: 531 
 +</​code>​ 
 +Acum, oricând avem nevoie de aceste informații,​ folosim one linerul. 
 + 
 +Desigur, nu ne oprim aici, ci vrem informații la nivelul fiecărei serii. 
 +Am putea realiza acest lucru tot cu un one-liner, ca mai jos, adăugând încă o secvență ''​for''​ care parcurge cele patru serii (''​CA'',​ ''​CB'',​ ''​CC'',​ ''​CD''​):​ 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ for year in *.csv; do for series in CA CB CC CD; do echo -n "​$(basename "​$year"​ .csv) - $series: " ; tail -n +2 "​$year"​ | grep "​$series"​ | wc -l; done; done 
 +2016-2017 - CA: 109 
 +2016-2017 - CB: 137 
 +2016-2017 - CC: 111 
 +2016-2017 - CD: 170 
 +2017-2018 - CA: 155 
 +2017-2018 - CB: 147 
 +2017-2018 - CC: 151 
 +2017-2018 - CD: 143 
 +2018-2019 - CA: 161 
 +2018-2019 - CB: 137 
 +2018-2019 - CC: 156 
 +2018-2019 - CD: 136 
 +2019-2020 - CA: 130 
 +2019-2020 - CB: 136 
 +2019-2020 - CC: 145 
 +2019-2020 - CD: 131 
 +</​code>​ 
 + 
 +Deja one-linerul este complicat. 
 +Este momentul să tranzităm la folosirea unui script, care e mai ușor de citit, de modificat, de utilizat și de menținut. 
 +Folosim scriptul ''​show_nums'':​ 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ cat ./​show_nums 
 +#​!/​bin/​bash 
 + 
 +if test $# -ne 1; then 
 +    echo "​Usage:​ $0 <​csv_file>"​ 1>&​2 
 +    exit 1 
 +fi 
 + 
 +csv_file="​$1"​ 
 +if test ! -f "​$csv_file";​ then 
 +    echo "​Error:​ Argument $csv_file is not a file." 1>&​2 
 +    exit 1 
 +fi 
 + 
 +for series in CA CB CC CD; do 
 +    echo -n "​$series:​ " 
 +    tail -n +2 "​$csv_file"​ | grep "​$series"​ | wc -l 
 +    for group in 311 312 313 314 315; do 
 +        echo -n "​$group$series:​ " 
 +        tail -n +2 "​$csv_file"​ | grep "​$group$series"​ | wc -l 
 +    done 
 +done 
 + 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_nums 
 +Usage: ./show_nums <​csv_file>​ 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./show_nums 2016-2017.csv 
 +CA: 109 
 +311CA: 28 
 +312CA: 27 
 +313CA: 27 
 +314CA: 27 
 +315CA: 0 
 +CB: 137 
 +311CB: 27 
 +312CB: 28 
 +313CB: 28 
 +314CB: 27 
 +315CB: 27 
 +CC: 111 
 +310CC: 27 
 +312CC: 28 
 +313CC: 28 
 +314CC: 28 
 +315CC: 0 
 +CD: 170 
 +311CD: 26 
 +312CD: 27 
 +313CD: 26 
 +314CD: 27 
 +315CD: 27 
 + 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./show_nums 2017-2018.csv 
 +[...] 
 + 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./show_nums 2018-2019.csv 
 +[...] 
 + 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./show_nums 2019-2020.csv 
 +[...] 
 + 
 +</​code>​ 
 +Scriptul ''​show_nums''​ primește ca argument chiar numele fișierului CSV. 
 +Parcurge fișierul și afișează informații la nivel de serie. 
 + 
 +Numărul de studenți este o informație relativ simplă. 
 +O informație mai valoroasă, pentru evaluarea disciplinei,​ a subiectelor și a pregătirii studenților,​ o reprezintă notele. 
 +Vrem să extragem media studenților. 
 +Pentru aceasta putem folosi one-linere și construcții shell: 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ tail -n +2 2016-2017.csv | cut -d','​ -f3 | grep -v '​^$'​ | paste -s -d'​+'​ | bc 
 +3657.0 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ sum=$(tail -n +2 2016-2017.csv | cut -d','​ -f3 | grep -v '​^$'​ | paste -s -d'​+'​ | bc) 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ count=$(tail -n +2 2016-2017.csv | wc -l) 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ echo "​scale=2;​ $sum/​$count"​ 
 +scale=2; 3657.0/​493 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ echo "​scale=2;​ $sum/​$count"​ | bc 
 +7.41 
 +</​code>​ 
 +Obținem că media notelor finale în anul universitar 2016-2017 este ''​7.41''​. 
 +Media este eronată: este media pentru toți studenții inclusiv cei absenți; variabila ''​count''​ nu a eliminat studenții absenți. 
 +O medie calculată corect este: 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ count=$(tail -n +2 2016-2017.csv | cut -d ','​ -f3 | grep -v '​^$'​ | wc -l) 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ echo "​scale=2;​ $sum/​$count"​ | bc 
 +7.96 
 +</​code>​ 
 +În secvența de mai sus, am eliminat intrările care nu conțin valoare (notele absente), la fel cum am procedat și în calculul sumei ''​sum''​. 
 + 
 +În plus, one-linerul nu este robust. 
 +Este posibil ca unele intrări să conțină șirul ''​ABS''​ sau ''​absent'',​ așa cum vedem că este cazul fișierului ''​2017-2018.csv'':​ 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ tail -n +2 2017-2018.csv | cut -d','​ -f3 | grep -v '​^$'​ | paste -s -d'​+'​ 
 +9.0+9.0+9.0+8.0+8.0+8.0+10.0+9.0+6.0+7.0+9.0+4.0+10.0+10.0+9.0+8.0+9.0+9.0+6.0+6.0+10.0+9.0+9.0+10.0+9.0+10.0+5.0+10.0+8.0+10.0+10.0+10.0+7.0+10.0+10.0+8.0+9.0+8.0+9.0+10.0+9.0+6.0+10.0+10.0+8.0+10.0+7.0+7.0+8.0+10.0+8.0+7.0+9.0+8.0+9.0+10.0+10.0+10.0+9.0+7.0+6.0+10.0+10.0+6.0+9.0+8.0+8.0+10.0+10.0+7.0+10.0+9.0+8.0+10.0+10.0+8.0+10.0+10.0+9.0+8.0+9.0+7.0+6.0+8.0+9.0+10.0+6.0+6.0+8.0+7.0+7.0+8.0+9.0+9.0+6.0+9.0+8.0+9.0+10.0+6.0+10.0+10.0+8.0+10.0+8.0+10.0+9.0+10.0+10.0+10.0+8.0+10.0+10.0+10.0+8.0+9.0+6.0+10.0+5.0+10.0+10.0+10.0+10.0+5.0+9.0+8.0+8.0+7.0+9.0+7.0+8.0+9.0+7.0+7.0+9.0+6.0+7.0+6.0+7.0+7.0+9.0+8.0+10.0+7.0+8.0+10.0+10.0+10.0+9.0+5.0+10.0+10.0+9.0+10.0+10.0+8.0+10.0+6.0+7.0+10.0+10.0+6.0+8.0+10.0+10.0+absent+9.0+7.0+9.0+8.0+9.0+8.0+6.0+4.0+10.0+9.0+10.0+8.0+8.0+7.0+9.0+8.0+10.0+10.0+7.0+9.0+9.0+8.0+7.0+7.0+8.0+7.0+8.0+7.0+10.0+6.0+7.0+8.0+9.0+10.0+5.0+7.0+6.0+9.0+6.0+7.0+6.0+8.0+8.0+9.0+8.0+absent+9.0+6.0+10.0+10.0+10.0+6.0+9.0+6.0+7.0+8.0+6.0+10.0+6.0+9.0+absent+absent+10.0+7.0+8.0+absent+7.0+8.0+9.0+8.0+9.0+9.0+6.0+absent+9.0+10.0+absent+10.0+10.0+9.0+10.0+8.0+8.0+7.0+8.0+8.0+10.0+absent+8.0+10.0+6.0+7.0+8.0+10.0+10.0+10.0+8.0+9.0+9.0+absent+7.0+10.0+8.0+9.0+7.0+10.0+9.0+6.0+8.0+10.0+7.0+7.0+10.0+10.0+10.0+10.0+10.0+8.0+7.0+8.0+8.0+10.0+10.0+8.0+10.0+9.0+8.0+9.0+10.0+9.0+7.0+8.0+9.0+9.0+10.0+6.0+9.0+10.0+8.0+10.0+10.0+6.0+10.0+9.0+9.0+7.0+8.0+7.0+7.0+10.0+ABS+4.0+9.0+10.0+10.0+7.0+ABS+10.0+7.0+9.0+10.0+10.0+10.0+10.0+10.0+10.0+10.0+9.0+8.0+8.0+10.0+10.0+10.0+9.0+9.0+9.0+5.0+10.0+8.0+10.0+8.0+8.0+10.0+8.0+ABS+ABS+10.0+8.0+7.0+10.0+10.0+9.0+10.0+9.0+8.0+7.0+10.0+10.0+7.0+10.0+10.0+10.0+8.0+7.0+9.0+10.0+9.0+10.0+10.0+10.0+10.0+10.0+7.0+9.0+ABS+10.0+ABS+4.0+8.0+6.0+8.0+10.0+10.0+6.0+7.0+8.0+9.0+9.0+10.0+9.0+8.0+9.0+8.0+9.0+8.0+8.0+9.0+5.0+10.0+7.0+5.0+10.0+8.0+9.0+10.0+8.0+6.0+10.0+8.0+10.0+8.0+8.0+8.0+7.0+9.0+10.0+7.0+8.0+9.0+9.0+7.0+absent+5.0+7.0+7.0+7.0+10.0+8.0+9.0+6.0+10.0+10.0+10.0+8.0+4.0+7.0+10.0+7.0+7.0+8.0+7.0+5.0+6.0+5.0+6.0+10.0+absent+9.0+7.0+9.0+10.0+9.0+7.0+10.0+7.0+6.0+10.0+7.0+6.0+9.0+9.0+absent+7.0+10.0+7.0+10.0+7.0+7.0+8.0+7.0+8.0+6.0+absent+7.0+9.0+7.0+6.0+7.0+absent+6.0+4.0+8.0+absent+8.0+8.0+7.0+9.0+7.0+10.0+8.0+6.0+8.0+9.0+10.0+6.0+10.0+4.0+7.0+absent+10.0+10.0+9.0+4.0+8.0+9.0+absent+7.0+8.0+6.0+8.0+5.0+9.0+8.0+6.0+7.0+8.0+7.0+10.0+9.0+7.0+7.0+6.0+9.0+10.0+9.0+8.0+7.0+10.0+10.0+7.0+10.0 
 +</​code>​ 
 + 
 +Ținând cont de aceasta, creăm scriptul ''​show_average_final''​ care rezolvă problemele de mai sus, și care împrumută bunele practici ale scriptului ''​show_num''​ ca să afișeze media fiecărui an universitar:​ 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_average_final 2016-2017.csv 
 +7.96 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_average_final 2017-2018.csv 
 +8.33 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_average_final 2018-2019.csv 
 +8.77 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_average_final 2019-2020.csv 
 +7.85 
 +</​code>​ 
 + 
 +Dacă ne dorim statistici și la nivelul seriei, actualizăm scriptul în scriptul ''​show_average_final_series'':​ 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_average_final_series 2019-2020.csv 
 +7.85 
 +CA: 8.17 
 +CB: 8.50 
 +CC: 7.74 
 +CD: 7.10 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_average_final_series 2018-2019.csv 
 +8.77 
 +CA: 8.76 
 +CB: 8.39 
 +CC: 8.94 
 +CD: 8.84 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_average_final_series 2017-2018.csv 
 +8.33 
 +CA: 8.68 
 +CB: 8.18 
 +CC: 8.57 
 +CD: 7.88 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ ./​show_average_final_series 2016-2017.csv 
 +7.96 
 +CA: 8.42 
 +CB: 7.94 
 +CC: 7.81 
 +CD: 7.86 
 +</​code>​ 
 + 
 +În momentul în care efectuăm prelucrări numerice și pe date din ce în ce mai multe și cu potențiale noi cerințe de prelucrarea,​ ne gândim să trecem la un limbaj de scripting / programare cu mai multe funcționalități de prelucrare numerică și de șiruri, care să permită o mai bună mentenanță. 
 +Un astfel de exemplu este scriptul ''​stats.py''​ în Python: 
 +<code bash> 
 +student@uso:​~/​uso-lab/​lectures/​auto/​grades$ python stats.py 
 +Grup           ​Număr ​   Notă    Quiz    Teme Midterm Practic 
 +2016-2017 ​       455    7.96    6.40    7.71    6.52    7.00 
 +CA               ​105 ​   8.42    6.94    7.65    6.75    8.01 
 +CB               ​123 ​   7.94    6.14    7.88    5.92    7.17 
 +CC               ​105 ​   7.82    6.01    7.42    7.01    6.83 
 +CD               ​122 ​   7.72    6.52    7.84    6.51    6.11 
 + 
 +2017-2018 ​       503    8.36    6.01    9.25    7.42    7.19 
 +CA               ​117 ​   8.64    6.71    9.27    7.09    7.13 
 +CB               ​134 ​   8.26    5.46    9.17    7.10    7.67 
 +CC               ​118 ​   8.74    6.86    9.33    7.87    7.57 
 +CD               ​134 ​   7.89    5.22    9.25    7.62    6.42 
 + 
 +2018-2019 ​       498    8.78    6.86    8.98    7.52    8.23 
 +CA               ​131 ​   8.82    6.97    8.93    7.52    8.76 
 +CB               ​122 ​   8.39    6.42    8.97    7.12    6.74 
 +CC               ​124 ​   9.02    7.05    9.15    7.43    8.67 
 +CD               ​121 ​   8.86    6.99    8.87    8.03    8.71 
 + 
 +2019-2020 ​       488    8.14    5.93    8.69    6.67    6.97 
 +CA               ​121 ​   8.31    6.12    8.62    6.69    7.80 
 +CB               ​125 ​   8.50    6.69    8.63    6.92    7.80 
 +CC               ​126 ​   8.07    6.26    8.61    6.80    6.06 
 +CD               ​116 ​   7.65    4.54    8.90    6.25    6.19 
 + 
 +</​code>​ 
 + 
 +În acest script facem o prelucrare a tuturor notelor: final, examen grilă, teme, examen practic final și de midterm. 
 +Scriptul folosește funcționalități ale limbajului Python: clase, dicționare,​ funcții, parcurgerea fișierelor (CSV). 
 +Aceste lucruri îl fac ușor de actualizat și de meținut. 
 + 
 +Concluzionând,​ atunci când facem automatizare:​ 
 +  * folosim funcționalități existente ale shellului 
 +  * pornim cu înlănțuiri de comenzi și one linere 
 +  * pe măsură ce avansăm, trecem la scripturi shell 
 +  ​când prelucrăm șiruri sau numere și avem multe date și cerințe în creștere, tranzităm la un limbaj de scripting ​programare (precum Python)
  
-/* 
-  * **Suport de curs** 
-    * [[http://​elf.cs.pub.ro/​uso/​res/​carte/​uso_cap-13-auto.pdf|Capitolul 13: Automatizarea sarcinilor]] 
-*/ 
  
 /* /*
  
-====== Curs 11 Elemente de securitate ​=======+====== Curs 10 Securitatea sistemului ​=======
  
-  * [[http://elf.cs.pub.ro/uso/​res/​cursuri/​curs-11/​curs-11-handout.pdf ​| Slide-uri curs]] +  * [[https://drive.google.com/open?id=1R-pS_BAVlEy4mHS3Zjf9h7X13fSVlCgr|Slide-uri curs]] 
-  * [[http://elf.cs.pub.ro/uso/res/cursuri/curs-11/​curs-11-handout-4on1-notes.pdf ​Handout 4on1 and notes space]] +  * [[https://drive.google.com/file/d/1k2YOlX247w5aGUt0ptmwHTOZ6CFZEoXh/view?​usp=sharing|Handouts 3on1 and notes space]] 
-  * [[http://elf.cs.pub.ro/uso/res/cursuri/​curs-11/curs-11-handout-8on1.pdf ​Handout 8on1]] +  * [[https://drive.google.com/file/d/1G-j69EsOEepRE1v3102gUa1OG65UgbgP/view?​usp=sharing|Handouts 6on1]] 
-  * **Cuvinte cheie**: ​securitate, privilegii, principii de securitate, agenți, obiecte, ''​umask'',​ autentificare,​ autorizare, controlul accesului, ''​root'',​ ''​sudo'',​ parole, //password cracking//, //​passphrase//,​ ''/​etc/​passwd'',​ ''/​etc/​shadow'',​ criptografie,​ criptare, decriptare, //plain text//, //​ciphertext//,​ chei simetrice, chei asimetrice, semnătură digitală, semnare, verificare+  * **Cuvinte cheie**: ​
   * **Suport de curs**   * **Suport de curs**
 +    * [[http://​elf.cs.pub.ro/​uso/​res/​carte/​uso_cap-12-sec.pdf|Capitolul 12: Securitatea sistemului]]
     * [[http://​books.google.com/​books?​id=_JFGzyRxQGcC | Introducere în sisteme de operare]]     * [[http://​books.google.com/​books?​id=_JFGzyRxQGcC | Introducere în sisteme de operare]]
       * [[http://​books.google.com/​books?​id=_JFGzyRxQGcC&​pg=PA279 | Capitolul 10 - Elemente de securitate]]       * [[http://​books.google.com/​books?​id=_JFGzyRxQGcC&​pg=PA279 | Capitolul 10 - Elemente de securitate]]
- 
-<​HTML>​ 
-  <​center>​ 
-    <iframe src="​https://​docs.google.com/​viewer?​url=http://​elf.cs.pub.ro/​uso/​res/​cursuri/​curs-11/​curs-11-handout.pdf&​embedded=true"​ width="​600"​ height="​480"​ style="​border:​ none;">​ 
-    </​iframe>​ 
-  </​center>​ 
-</​HTML>​ 
  
 ===== Demo-uri ===== ===== Demo-uri =====
Line 350: Line 624:
 Pentru criptare/​decriptare și semnare/​verifcare cu chei asimetrice putem folosi și suita [[https://​www.gnupg.org/​|GnuPG]] (//GNU Privacy Guard//). Pentru criptare/​decriptare și semnare/​verifcare cu chei asimetrice putem folosi și suita [[https://​www.gnupg.org/​|GnuPG]] (//GNU Privacy Guard//).
 </​note>​ </​note>​
 +
 +/*
 +
 +====== Curs 10 - Shell scripting =======
 +
 +  * [[http://​elf.cs.pub.ro/​uso/​res/​cursuri/​curs-10/​curs-10-handout.pdf | Slide-uri curs]]
 +  * [[http://​elf.cs.pub.ro/​uso/​res/​cursuri/​curs-10/​curs-10-handout-4on1-notes.pdf | Handout 4on1 and notes space]]
 +  * [[http://​elf.cs.pub.ro/​uso/​res/​cursuri/​curs-10/​curs-10-handout-8on1.pdf | Handout 8on1]]
 +  * **Cuvinte cheie**: variabile, variabile de mediu, escaping, expandare, one liner, filtru de text, script shell, ''​IFS'',​ ''​while read'',​ ''​for'',​ ''​if'',​ expresii regulate, metacaractere,​ globbing, ''​grep'',​ prelucrare de date, automatizare
 +  * **Suport de curs**
 +    * Suport (Introducere în sisteme de operare)
 +      * Capitolul 12 -- Shell scripting
 +        * Secțiunile 12.4, 12.5, 12.6, 12.9
 +    * [[http://​www.amazon.com/​Regular-Expressions-Cookbook-Jan-Goyvaerts/​dp/​1449319432|Regular Expressions Cookbook]]
 +      * Puteți descărca fișierul PDF aferent de [[https://​github.com/​shihyu/​Regular_Expressions|aici]].
 +      * Capitolul 1 -- Introduction to Regular Expressions
 +      * Capitolul 2 -- Basic Regular Expression Skills
 +
 +<​HTML>​
 +  <​center>​
 +    <iframe src="​https://​docs.google.com/​viewer?​url=http://​elf.cs.pub.ro/​uso/​res/​cursuri/​curs-10/​curs-10-handout.pdf&​embedded=true"​ width="​600"​ height="​480"​ style="​border:​ none;">​
 +    </​iframe>​
 +  </​center>​
 +</​HTML>​
 +
 +===== Demo-uri =====
 +
 +Pentru rularea demo-urilor de mai jos folosim [[http://​repository.grid.pub.ro/​cs/​uso/​USO%20Demo.ova|mașina virtuală USO Demo]]. Mașina virtuală (în format OVA) poate fi importată în VirtualBox. Comenzile le vom rula în cadrul mașinii virtuale.
 +
 +Mașina virtuală deține două interfețe de rețea:
 +  * ''​eth0''​ pentru accesul la Internet (interfață de tipul NAT)
 +  * ''​eth1''​ pentru comunicarea cu sistemul fizic (gazdă, //host//) (interfață de tipul //Host-only Adapter//)
 +
 +Pentru a rula demo-ul avem două opțiuni:
 +  - Folosim direct consola mașinii virtuale.
 +  - Aflăm adresa IP de pe interfața ''​eth1''​ a mașinii virtuale și ne conectăm prin SSH, de pe sistemul fizic, folosind comanda<​code>​
 +ssh student@<​adresa-IP-vm-eth1>​
 +</​code>​ unde ''<​adresa-IP-vm-eth1>''​ este adresa IP a interfeței ''​eth1''​ din cadrul mașinii virtuale.
 +
 +Pentru conectarea la mașina virtuală folosim numele de utilizator ''​student''​ cu parola ''​student''​. Contul ''​student''​ are permsiuni de ''​sudo''​. Folosind comanda<​code>​
 +sudo su -
 +</​code>​
 +obținem permisiuni privilegiate (de ''​root''​) în shell.
 +
 +<​note>​
 +Dacă dorim să ne conectăm pe SSH iar mașina virtuală nu are adresă IP configurată pe interfața ''​eth1''​ atunci folosim comanda<​code>​
 +sudo dhclient eth1
 +</​code>​
 +pentru a obține o adresă IP.
 +</​note>​
 +
 +<​note>​
 +Dacă optăm pentru rularea prin SSH iar sistemul fizic rulează Windows, putem folosi [[http://​www.chiark.greenend.org.uk/​~sgtatham/​putty/​|Putty]] pe post de client SSH pe sistemul fizic.
 +</​note>​
 +
 +<​note>​
 +Comenzile folosite sunt de uz general. Actualizând adresele IP cu adrese potrivite, putem rula cu succes comenzile pe orice sistem sau mașină virtuală Linux.
 +</​note>​
 +
 +==== Obținere arhivă ====
 +
 +Pentru parcurgerea demo-urilor,​ folosim [[http://​elf.cs.pub.ro/​uso/​res/​cursuri/​curs-10/​curs-10-demo.zip|arhiva aferentă]]. Descărcăm arhiva în mașina virtuală (sau în orice alt mediu Linux) folosind comanda<​code bash>
 +student@uso-demo:​~$ wget http://​elf.cs.pub.ro/​uso/​res/​cursuri/​curs-10/​curs-10-demo.zip
 +[...]
 +</​code>​ și apoi dezarhivăm arhiva<​code bash>
 +student@uso-demo:​~$ unzip curs-10-demo.zip ​
 +[...]
 +</​code>​ și accesăm directorul rezultat în urma dezarhivării<​code bash>
 +student@uso-demo:​~$ cd curs-10-demo/​
 +student@uso-demo:​~/​curs-10-demo$ ls
 +user-results.csv
 +</​code>​
 +
 +Acum putem parcurge secțiunile cu demo-uri de mai jos. Vom folosi resursele din directorul rezultat în urma dezarhivării.
 +
 +==== Splitting folosind cut ====
 +
 +Pentru splitting simplu de date tabelare putem folosi utilitarul ''​cut''​. Acesta permite precizarea unui delimitator și a unui câmp sau a mai multor câmpuri (coloane) care să fie selectate din tabel.
 +
 +Din fișierul ''​user-results.csv''​ (format CSV -- //Comma Separated Values//) dorim să selectăm doar numele grupurilor. Pentru aceasta selectăm doar a doua coloană și folosim separatorul '',''​ (virgulă) folosind comanda<​code>​
 +student@uso-demo:​~/​curs-11-demo$ cut -d ','​ -f 2 < user-results.csv
 +Liceul Teoretic Ștefan Odobleja
 +Colegiul Național Ion Maiorescu
 +Colegiul Tehnic Toma Socolescu
 +Colegiul Național Nichita Stănescu
 +Liceul Teoretic Benjamin Franklin
 +Colegiul Național I.L. Caragiale
 +Colegiul Național Zinca Golescu
 +[...]
 +</​code>​
 +
 +Dacă dorim să "​unicizăm"​ rezultatele și să afișăm doar numele liceelor putem conecta comanda de mai sus la o comandă ''​sort'':<​code>​
 +student@uso-demo:​~/​curs-11-demo$ cut -d ','​ -f 2 < user-results.csv | sort -u
 +
 +Colegiul Economic Virgil Madgearu
 +Colegiul Național Alexandru Odobescu
 +Colegiul Național Barbu Știrbei
 +Colegiul Național Cantemir Vodă
 +Colegiul Național Carol I
 +Colegiul Național Gheorghe Lazăr
 +[...]
 +</​code>​
 +În urma rulării comenzii de mai sus ne sunt afișate doar numele liceelor.
 +
 +Dacă ne interesează să afișăm **doar** identificatorii utilizatorilor și punctajele obținute, atunci folosim comanda<​code>​
 +student@uso-demo:​~/​curs-11-demo$ cut -d ','​ -f 1,4 < user-results.csv | head
 +ionut.asimionesei,​0
 +laura.matei,​66
 +alin.dascalu,​285
 +dragos.konnerth,​42
 +alexandru.corneanu,​247
 +alexandru.tittes,​154
 +[...]
 +</​code>​
 +
 +<​note>​
 +Utilitarul ''​cut''​ are două opțiuni frecvent folosite:
 +  * opțiunea ''​-d''​ care precizează delimitatorul de câmpuri (//field delimiter// sau //field separator//​)
 +  * opțiunea ''​-f''​ care precizează ce câmpuri/​coloane dorim să extragem
 +</​note>​
 +
 +==== Splitting și prelucrare folosind while read ====
 +
 +Utilitarul ''​cut''​ are dezavantajul că face doar splitting și extrage câmpuri/​coloane. Nu putem condiționa extragerea unor câmpuri. De exemplu, dacă dorim extragerea conturilor care au punctaj mai mare ca 500, nu vom putea folosi ''​cut''​. Putem însă folosi construcția ''​while read''​ într-un script shell.
 +
 +Pentru a extrage conturile care au punctaj mai mare ca 500, vom folosi scriptul ''​extract-points-500''​ de mai jos:
 +<file Bash extract-points-500>​
 +#!/bin/bash
 +
 +IFS=','​
 +while read uid school date points; do
 +    if test "​$points"​ -ge 500; then
 +        echo "​$uid"​
 +    fi
 +done < user-results.csv
 +</​file>​
 +Rulăm scriptul folosind comanda<​code>​
 +student@uso-demo:​~/​curs-11-demo$ ./​extract-points-500 ​
 +mihaela.croitoru
 +andreea.cismas
 +elvis.titirca
 +mihaela.serbana
 +anjie.teodorescu
 +[...]
 +</​code>​
 +În scriptul ''​extract-points-500''​ am folosit construcția ''​while read''​ pentru a face split la cele patru coloane din fișierul ''​user-results.csv''​. Separatorul (delimitatorul) l-am definit cu ajutorul variabilei ''​IFS''​ (//Input Field Separator//​) pe care am inițializat-o la '',''​ (virgulă). După split am folosit construcția ''​if''​ pentru a afișa doar conturile utilizatorilor cu punctaj peste ''​500''​.
 +
 +Dacă dorim să afișăm și punctajul obținut (nu doar contul) atunci trebuie doar să modificăm linia de afișare (care folosește comanda ''​echo''​). Rezultatul va fi scriptul actualizat și cu rularea de mai jos:<​code>​
 +student@uso-demo:​~/​curs-11-demo$ cat extract-points-500 ​
 +#!/bin/bash
 +
 +IFS=','​
 +while read uid school date points; do
 +    if test "​$points"​ -ge 500; then
 +        echo "​$uid,​$points"​
 +    fi
 +done < user-results.csv
 +
 +student@uso-demo:​~/​curs-11-demo$ ./​extract-points-500
 +mihaela.croitoru,​516
 +andreea.cismas,​803
 +elvis.titirca,​501
 +mihaela.serbana,​526
 +anjie.teodorescu,​666
 +georgiana.ciobanica,​1047
 +[...]
 +</​code>​
 +
 +Dacă în output-ul de mai sus dorim să avem sortare în ordine descrescătoare a punctajului,​ înlănțuim o comandă ''​sort''​ care să sorteze numeric, descrescător după a doua coloană<​code>​
 +student@uso-demo:​~/​curs-11-demo$ ./​extract-points-500 | sort -t ','​ -k 2,2rn
 +radu.dumitru5227,​21433
 +mihaela.catai,​13623
 +stefania.oprea,​9547
 +alexandra.calinescu,​5266
 +george.ungureanu,​3846
 +dragos.totu,​2040
 +monica.cirisanu,​1815
 +</​code>​
 +În comanda de mai sus, comanda ''​sort''​ sortează output-ul scriptului folosind ca separator virgulă (construcția ''​%%-t ','​%%''​ după a două coloană (construcția ''​-k 2,​2''​) descrescător numeric (construcția ''​rn''​).
 +
 +<​note>​
 +Construcția ''​while read''​ este folosită pentru a putea face prelucrări pe fiecare linie procesată, nu doar splitting, așa cum face comanda ''​cut''​.
 +</​note>​
 +
 +==== Splitting și prelucrare folosind awk ====
 +
 +Construcția ''​while read''​ este utilă pentru realizarea de splitting și de prelucări minimale. Prelucrările pe care le poate face țin de facilitățile pe care le oferă shell-ul.
 +
 +Pentru prelucrări mai avansate recomandăm folosirea utilitarului ''​awk''​. Utilitarul ''​awk''​ are în spate un limbaj propriu, asemănător limbajului C, și are suport de expresii regulate. Este un utilitar puternic util pentru prelucrarea datelor în format text.
 +
 +Pentru a obține același efect cu al scriptului ''​extract-points-500''​ putem folosi oneliner-ul de mai jos:<​code>​
 +student@uso-demo:​~/​curs-11-demo$ awk -F ','​ '{ if ($4 >= 500) print $1;}' < user-results.csv ​
 +mihaela.croitoru
 +andreea.cismas
 +elvis.titirca
 +mihaela.serbana
 +anjie.teodorescu
 +georgiana.ciobanica
 +[...]
 +</​code>​
 +
 +Pentru a afișa și punctajul folosim one liner-ul:<​code>​
 +student@uso-demo:​~/​curs-11-demo$ awk -F ','​ '{ if ($4 >= 500) print $1 ","​ $4;}' < user-results.csv ​
 +mihaela.croitoru,​516
 +andreea.cismas,​803
 +elvis.titirca,​501
 +mihaela.serbana,​526
 +anjie.teodorescu,​666
 +georgiana.ciobanica,​104
 +[...]
 +</​code>​
 +
 +Observăm că pentru ''​awk''​ separatorul este dat de opțiunea ''​-F'',​ iar sintaxa este similară cu cea a limbajului C. Un câmp/​coloană este indicat de construcția ''​$N''​ unde ''​N''​ este indexul câmpului; în cazul nostru am folosit ''​$1''​ și ''​$4''​ pentru cont și punctaj, respectiv.
 +
 +După cum am precizat, ''​awk''​ are suport de expresii regulate. Dacă, de exemplu, din output-ul de mai sus dorim să extragem doar liniile care au un nume de cont al cărui nume de familie începe cu litera ''​c'',​ vom folosi construcția:<​code>​
 +student@uso-demo:​~/​curs-11-demo$ awk -F ','​ '$1 ~ /[^\.]+\.c/ { if ($4 >= 500) print $1 ","​ $4;}' < user-results.csv ​
 +mihaela.croitoru,​516
 +andreea.cismas,​803
 +georgiana.ciobanica,​1047
 +ion.camasa,​502
 +mihaela.catai,​13623
 +alexandra.cismaru,​860
 +[...]
 +</​code>​
 +În one liner-ul de mai sus, am selectat doar acele linii pentru care primul câmp (''​$1''​) face match pe expresia regulată ''​%%[^\.]+\.c%%''​ (adică numele de familie începe cu litera ''​c''​).
 +
 +<​note>​
 +În awk, sed și alte utilitare similare expresiile regulate se plasează între slash-uri; mai sus a fost vorba de ''​%%/​[^\.]+\.c/​%%''​.
 +</​note>​
 +
 +Același rezultat ca mai sus putea fi realizat și cu ajutorul comenzii ''​grep''​ legată de la comanda ''​awk'',​ ca mai jos:<​code>​
 +student@uso-demo:​~/​curs-11-demo$ awk -F ','​ '{ if ($4 >= 500) print $1 ","​ $4;}' < user-results.csv | grep '​^[^\.]\+\.c'​
 +mihaela.croitoru,​516
 +andreea.cismas,​803
 +georgiana.ciobanica,​1047
 +ion.camasa,​502
 +mihaela.catai,​13623
 +alexandra.cismaru,​860
 +[...]
 +</​code>​
 +Rezultatul este același și poate părea mai simplu să folosim ''​grep''​. Doar că ''​awk''​ permite match cu expresie regulată pe un câmp specific primit la intrare; se poate forța acest lucru și cu ''​grep''​ dar devine mai puțin clar.
 +
 +În momentul în care un script ''​awk''​ devine mai complicat, poate fi plasat într-un script shell, așa cum este în fișierul ''​extract-points-500-awk'':​
 +<file Bash extract-points-500-awk>​
 +#!/bin/bash
 +
 +awk -F ','​ '
 +$1 ~ /[^\.]+\.c/ {
 +    if ($4 >= 500)
 +        print $1 ","​ $4;
 +    }
 +' < user-results.csv
 +</​file>​
 +Rulăm scriptul folosind comanda<​code>​
 +student@uso-demo:​~/​curs-11-demo$ ./​extract-points-500-awk
 +mihaela.croitoru,​516
 +andreea.cismas,​803
 +georgiana.ciobanica,​1047
 +[...]
 +</​code>​
 +Scriptul ''​extract-points-500-awk''​ face același lucru ca one liner-ul anterior doar că este mai lizibil.
 +
 +<​note>​
 +În general, dacă utilizatorul dorește să obțină un efect rapid și cu șanse mici de repetare, va folosi un one liner. Altfel, va folosi un script shell pe care îl poate actualiza șî rula în mod repetat.
 +</​note>​
 +
 +==== Splitting și prelucrare folosind Python ====
 +
 +Pentru prelucrări complexe sau pentru integrarea prelucrărilor cu alte componente ale unei aplicații, inclusiv ''​awk''​ poate fi insuficient. În acest caz programatorul va apela la un limbaj specific precum Python, Perl, Ruby, Lua, Java, JavaScript sau altul.
 +
 +În fișierul ''​extract-points-500.py''​ de mai jos avem implementarea în Python a aceleiași funcționalități ca mai sus pentru ''​awk''​
 +<file Python extract-points-500.py>​
 +#​!/​usr/​bin/​env python
 +
 +import sys
 +import re
 +
 +
 +def main():
 +    for line in open("​user-results.csv",​ "​rt"​):​
 +        line = line.rstrip("​\n"​)
 +        uid, school, date, points = line.split(","​)
 +        if re.match("​[^\.]+\.c",​ uid):
 +            if int(points) >= 500:
 +                print "​%s,​%s"​ % (uid,​points)
 +
 +
 +if __name__ == "​__main__":​
 +    sys.exit(main())
 +</​file>​
 +În cadrul scriptului citim linie cu linie conținutul fișierului ''​user-results.csv''​ și apoi este splitted și se extrag liniile pentru care numele contului are un nume de familie care începe cu litere ''​c''​ și punctajul este mai mare ca ''​500''​.
 +
 +Rularea scriptului Python conduce la același rezultat ca în cazul folosirii ''​awk'':<​code>​
 +student@uso-demo:​~/​curs-11-demo$ ./​extract-points-500.py ​
 +mihaela.croitoru,​516
 +andreea.cismas,​803
 +georgiana.ciobanica,​1047
 +ion.camasa,​502
 +mihaela.catai,​13623
 +alexandra.cismaru,​860
 +[...]
 +</​code>​
 +
 +Python oferă o flexibilitate superioară ''​awk''​ cu dezavantajul unei complexități mai mari a codului. Pentru acțiuni rapide, integrabile cu shell scripting, ''​awk''​ este o bună alegere (sau ''​while read''​);​ pentru acțiuni mai complexe, un limbaj de programare dedicat, precum Python poate fi o soluție.
 +
 +De exemplu, putem augmenta scriptul anterior pentru a afișa doar informații despre acele conturi care s-au autentificat prima oară în luna aprilie. Adică al treilea câmp este din luna aprilie. Pentru aceasta folosim scriptul ''​extract-points-500-date.py''​ din director:
 +<file Python extract-points-500-date.py>​
 +#​!/​usr/​bin/​env python
 +
 +import sys
 +import re
 +from datetime import datetime
 +
 +
 +def main():
 +    for line in open("​user-results.csv",​ "​rt"​):​
 +        line = line.rstrip("​\n"​)
 +        uid, school, date, points = line.split(","​)
 +        date_compare = datetime.strptime("​2015-04-01 00:​00:​00",​ "​%Y-%m-%d %H:​%M:​%S"​)
 +        try:
 +            date_in_format = datetime.strptime(date,​ "​%Y-%m-%d %H:​%M:​%S"​)
 +        except:
 +            continue
 +        if re.match("​[^\.]+\.c",​ uid):
 +            if int(points) >= 500:
 +                if date_in_format > date_compare:​
 +                    print "​%s,​%s,​%s"​ % (uid,​date,​points)
 +
 +
 +if __name__ == "​__main__":​
 +    sys.exit(main())
 +</​file>​
 +În scriptul de mai sus am comparat data (al treilea câmp) cu data de 1 aprilie 2015 și am afișat acele câmpuri pentru care câmpul dată era mai târziu de 1 aprilie 2015. Acest lucru ar fi putut fi realizat în ''​awk''​ dar ar fi complicat scriptul.
 +
 +Pentru rularea scriptului, folosim construcția<​code>​
 +student@uso-demo:​~/​curs-11-demo$ ./​extract-points-500-date.py ​
 +mihaela.catai,​2015-04-16 12:​29:​26,​13623
 +andra.cristiev,​2015-04-22 13:​08:​57,​865
 +</​code>​
 +
 +<​note>​
 +Decizia de folosire ''​cut''​ sau ''​while read''​ sau ''​awk''​ sau Python ține atât de datele și complexitatea problemei cât și de experiența utilizatorului/​dezvoltatorului. În general, recomandăm "use the best tool for the best job"; dacă un utilitar simplu poate face ce aveți nevoie, folosiți-l pe acela, chiar dacă un utilitar mai complex are mai multe caracteristici;​ dacă acele caracteristici nu sunt utile, nu are sens să-l folosiți.
 +</​note>​
 +
 +==== Folosire expresii regulate în sed ====
 +
 +Mai sus am folosit cu ''​awk'',​ ''​grep''​ și Python expresii regulate. Adesea, în linia de comandă veți folosi expresii regulate folosind comanda ''​grep''​. Dar și în alte situații, fie în linie de comandă, fie în scripting, fie în limbaje de programare, expresiile regulate sunt utile.
 +
 +În particular, utilitarul ''​sed''​ folosește expresii regulate. Unul dintre cazurile frecvente de utilizare a ''​sed''​ este pe post de editor neinteractiv,​ care să înlocuiască (substituie) elemente de pe o linie cu alte elemente.
 +
 +Dacă dorim, de exemplu, să înlocuim toate prenumele din numele de cont nu șirul ''​aaa''​ vom folosi un one liner precum cel de mai jos:<​code>​
 +student@uso-demo:​~/​curs-11-demo$ sed '​s/​^[^\.]\+/​aaa/​g'​ < user-results.csv
 +aaa.asimionesei,​Liceul Teoretic Ștefan Odobleja,​2015-03-31 16:18:01,0
 +aaa.matei,​Colegiul Național Ion Maiorescu,​2015-03-17 11:04:49,66
 +aaa.dascalu,​Colegiul Tehnic Toma Socolescu,​None,​285
 +aaa.konnerth,​Colegiul Național Nichita Stănescu,​None,​42
 +aaa.corneanu,​Liceul Teoretic Benjamin Franklin,​2015-03-18 10:​26:​21,​247
 +[...]
 +</​code>​
 +La fel ca în cazul ''​awk''​ expresia regulată se plasează între slash-uri. Expresia regulată folosită ''​%%^[^\.]\+%%''​ face match pe începutul de linie și pe șiruri de cel puțin o literă care nu conțin punct (''​.'',​ //dot//). Adică exact pe prenumele din numele de cont.
 +
 +Dacă dorim să eliminăm prenumele (împreună cu punctul) din numele de cont vom folosi o construcție precum<​code>​
 +student@uso-demo:​~/​curs-11-demo$ sed '​s/​^[^\.]\+\.//​g'​ < user-results.csv
 +asimionesei,​Liceul Teoretic Ștefan Odobleja,​2015-03-31 16:18:01,0
 +matei,​Colegiul Național Ion Maiorescu,​2015-03-17 11:04:49,66
 +dascalu,​Colegiul Tehnic Toma Socolescu,​None,​285
 +konnerth,​Colegiul Național Nichita Stănescu,​None,​42
 +corneanu,​Liceul Teoretic Benjamin Franklin,​2015-03-18 10:​26:​21,​247
 +[...]
 +</​code>​
 +În one liner-ul de mai sus am lăsat ca șir care substituie șirul vid (adică două slash-uri consecutive). Adică înlocuim partea pe care face match expresia regulată (adică prenumele din cont și caracterul punct) cu nimic, adică o ștergem.
 +
 +O situație poate fi să fie înlocuită construcția ''​prenume.nume''​ cu ''​nume.prenume''​ în numele contului. Pentru aceasta folosim construcția<​code>​
 +student@uso-demo:​~/​curs-11-demo$ sed '​s/​^\([^\.]\+\)\.\([^\,​]\+\),/​\2.\1,/​g'​ < user-results.csv
 +asimionesei.ionut,​Liceul Teoretic Ștefan Odobleja,​2015-03-31 16:18:01,0
 +matei.laura,​Colegiul Național Ion Maiorescu,​2015-03-17 11:04:49,66
 +dascalu.alin,​Colegiul Tehnic Toma Socolescu,​None,​285
 +konnerth.dragos,​Colegiul Național Nichita Stănescu,​None,​42
 +corneanu.alexandru,​Liceul Teoretic Benjamin Franklin,​2015-03-18 10:​26:​21,​247
 +[...]
 +</​code>​
 +Expresia regulată folosită mai sus (''​%%^\([^\.]\+\)\.\([^\,​]\+\),​%%''​) o decodificăm în următoarele componente:
 +  * ''​%%^%%'':​ început de linie
 +  * ''​%%\([^\.]\+\)%%'':​ face match pe prenume, adică șirul format din cel puțin un caracter diferit de punct; reține acest șir într-o variabilă (variabila este referită prin construcția ''​%%\1%%''​)
 +  * ''​%%\.%%'':​ face match pe caracterul punct (''​.'',​ //dot//) care separă prenumele de nume în cont
 +  * ''​%%\([^\,​]\+\)%%'':​ face match pe nume, adică șirul format din cel puțin un caracter diferit de virgulă; reține acest șir într-o variabilă (variabila este referită prin construcția ''​%%\2%%''​)
 +  * ''​%%,​%%'':​ face match pe caracterul virgulă ('','',​ //comma//) care urmează după cont
 +
 +Partea de înlocuit este ''​\2.\1,''​ adică numele de cont este înlocuit cu nume, urmat de punct, urmat de prenume, urmat de virgulă, așa cum ne-am dorit.
 +
 +<​note>​
 +La fel ca în cazul ''​awk'',​ ''​sed''​ este un utilitar adecvat pentru one linere, acțiuni rapide și încorporare în shell scripting. Pentru scenarii de utilizare mai complexe, recomandăm folosirea unor limbaje dedicate precum Python, Perl, Ruby, Java, JavaScript.
 +</​note>​
 +==== Automatizare folosind shell scripting ====
 +
 +Folosirea shell scripting și a one line-erelor are, de principiu, 3 scenarii de utilizare:
 +  * conectarea/​înlănțuirea mai multor comenzi pentru a obține un rezultat nou pentru un caz punctual de utilizare
 +  * automatizarea unei acțiuni: acțiunile pot fi repetitive și atunci o implmentare poate fi rulată de mai multe ori
 +  * prelucrarea datelor: folosind comenzi și construcții de tip filtre de text (''​cut'',​ ''​while read'',​ ''​tr'',​ ''​grep'',​ ''​sort'',​ ''​awk'',​ ''​sed''​) se prelucrează date în format text
 +
 +Partea de automatizare este utilă atunci când vrem să executăm o acțiune în mod repetat. Un caz de utilizare este când vrem să prelucrăm în același mod mai multe fișiere.
 +
 +De exemplu, având în vedere conținutul subdirectorului ''​horde/'',​ vrem să creăm copii de lucru ale fișierelor de configurare de distribuție. Fișierele de distribuție au extensia ''​.dist''​ (de exemplu ''​conf.php.dist''​);​ o copie de lucru este un fișier fără extensia ''​.dist''​ (de exemplu: ''​conf.php''​).
 +
 +Pentru a crea copie de lucru putem folosi următorul one liner, construit pas cu pas:<​code>​
 +student@uso-demo:​~/​curs-11-demo$ find horde/ -name '​*.dist'​
 +horde/​ingo/​config/​hooks.php.dist
 +horde/​ingo/​config/​prefs.php.dist
 +[...]
 +
 +student@uso-demo:​~/​curs-11-demo$ for f in $(find horde/ -name '​*.dist'​);​ do echo "​$f";​ done
 +horde/​ingo/​config/​hooks.php.dist
 +horde/​ingo/​config/​prefs.php.dist
 +[...]
 +
 +student@uso-demo:​~/​curs-11-demo$ for f in $(find horde/ -name '​*.dist'​);​ do echo "​${f/​.dist/​}";​ done
 +horde/​ingo/​config/​hooks.php
 +horde/​ingo/​config/​prefs.php
 +[...]
 +
 +student@uso-demo:​~/​curs-11-demo$ for f in $(find horde/ -name '​*.dist'​);​ do cp "​$f"​ "​${f/​.dist/​}";​ done
 +</​code>​
 +În ultima comandă avem one liner-ul care creează câte o copie a fișierului de distribuție într-un fișier de lucru. Construcția ''​${f/​.dist/​}''​ este folosită pentru a înlocui în valoarea variabilei ''​f''​ șirul ''​.dist''​ cu nimic, adică șterge acel șir, rezultând numele fișierului fără extensia ''​.dist''​.
 +
 +Pentru verificare folosim comanda ''​find''​ pentru a valida existența fișierelor de lucru:<​code>​
 +student@uso-demo:​~/​curs-11-demo$ find horde/ -name '​*.php'​
 +horde/​ingo/​config/​prefs.php
 +horde/​ingo/​config/​backends.php
 +[...]
 +</​code>​
 +
 +One liner-ul de mai sus este util o singură dată, pentru acele fișiere și de acceea nu are sens să îl trecem într-un script pe care să îl rulăm periodic, la nevoia, ca automatizare.
 +
 +Un exemplu de script folosit pentru automatizare este scriptul ''​publish-slides''​ folosit pentru publicarea slide-urilor de cursuri de USO. Nu veți putea rula scriptul în absența fișierelor de suport, dar este reprezentantiv pentru ceea ce înseamnă automatizarea unei sarcini repetitive: publicarea slide-urilor cursului de USO intern în cadrul echipei (în Dropbox) și studenților.
 +<file Bash publish-slides>​
 +#!/bin/bash
 +
 +dropbox_folder=~/​Downloads/​Dropbox/​school/​uso-shared
 +remote_end=uso@elf.cs.pub.ro:​res/​current/​cursuri
 +
 +if test $# -eq 1; then
 +    id=$(printf "​%02g"​ $1)
 +    pushd curs-$id/ > /dev/null 2>&1
 +    make all
 +    cp *.pdf "​$dropbox_folder"/​curs-$id/​
 +    scp *handout*.pdf "​$remote_end"/​curs-$id/​
 +    popd > /dev/null 2>&1
 +    exit 0
 +fi
 +
 +for id in $(seq -f "​%02g"​ 0 13); do
 +    pushd curs-$id/ > /dev/null 2>&1
 +    make all
 +    cp *.pdf "​$dropbox_folder"/​curs-$id/​
 +    scp *handout*.pdf "​$remote_end"/​curs-$id/​
 +    popd > /dev/null 2>&1
 +done
 +</​file>​
 +
 +Scriptul compilează (folosind ''​make''​) slide-urile cursului primit ca argument, sau toate slide-urile în absența argumentelor. Folosește ''​cp''​ pentru a copia slide-urile intern echipei, în Dropbox, și folosește ''​scp''​ pentru a publica slide-urile către studenți.
  
 */ */
uso/cursuri/curs-11.1610958198.txt.gz · Last modified: 2021/01/18 10:23 by ebru.resul
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0