This shows you the differences between two versions of the page.
sde:teme:tema_ro_3_python [2020/04/02 17:00] ioana_maria.culic |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Tema 3 - Mini-shell ====== | ||
- | |||
- | Scopul acestei teme este realizarea unui shell simplu, compatibil cu ''sh''; | ||
- | |||
- | ===== Informații generale ===== | ||
- | |||
- | <note important> | ||
- | Deadline: **5 Aprilie, ora 23:55**\\ | ||
- | Punctaj: **2 puncte** din nota\\ | ||
- | Incarcarea temei: [[https://vmchecker.cs.pub.ro|vmchecker.cs.pub.ro]]\\ | ||
- | Incarcarea cu intarziere: **0.1 punct / zi** (maxim 4 zile)\\ | ||
- | </note> | ||
- | |||
- | ===== Cunoștințe evaluate ===== | ||
- | |||
- | * Folosirea functiilor POSIX pentru lucrul cu fisiere (''os.open'', ''os.read'', ''os.write'', ...) | ||
- | * Folosirea functiilor pentru lucrul cu procese (''os.fork'', ''os.exec'' si ''os.waitpid'', ...) | ||
- | * Intelegerea principiilor de lucuru cu fisier si procese | ||
- | |||
- | ===== Reguli ===== | ||
- | |||
- | - Tema trebuie sa contina un fisier Readme in care sa explicati cum ati facut tema (-0.1p) | ||
- | - Aveti voie sa folositi doar functii POSIX (biblioteca [[https://docs.python.org/3/library/os.html|os]]) | ||
- | - Aveti voie sa folositi doar limbajul Python (Python 3) | ||
- | - O temă care trece toate testele automate va obține 10 puncte din 10 (daca nu trișează folosind API interzis, cum ar fi funcția ''f.write()'', ''os.popen'', caz în care nu va fi punctată). | ||
- | |||
- | |||
- | ===== Copierea ===== | ||
- | |||
- | Tema se rezolva individual. Orice tentativa de copiere va rezulta in **0p** pentru tema respectiva. Vom utiliza si sisteme automate de detectare a copierii. Daca avem dubii, va vom adresa intrebari suplimentare legate de tema. | ||
- | |||
- | ===== Intrebari ===== | ||
- | |||
- | Daca aveti intrebari legate de tema, va rugam sa scrieti un issue pe repository-ul de github [[https://github.com/upb-fils/sde.git|repository]] cu titlul de forma //[mini-shell] <titlul intrebarii voastre>//. Aveti nevoie de un cont de github pentru | ||
- | a scrie intrebari. | ||
- | |||
- | <note warning> | ||
- | **NU PUBLICATI COD SURSA**. Acesta va fi considerata copiere si se va penaliza cu 0p pe tema pentru voi. | ||
- | </note> | ||
- | |||
- | Daca doriti sa primiti un email cand se pun intrebari noi sau cand apar raspunsuri, accesati github [[https://github.com/upb-fils/sde|repository]] si faceti click pe //Watch//. | ||
- | |||
- | ===== Mini Shell ===== | ||
- | |||
- | Să se implementeze un shell simplu, care suportă execuția de comenzi externe cu argumente multiple, comenzi interne, redirectări, pipe-uri. Shell-ul trebuie să suporte execuția de comenzi compuse, cu oricâți operatori. | ||
- | |||
- | <note> | ||
- | Comnezi interne: comenzi pe care shell-ul le execute: ''cd'', ''pwd'', ''exit'' ... | ||
- | Comenzi externe: comenzi care sunt de fapt executabile separate: ''ls'', ''vim'', ''tree'', ''nano'', ... | ||
- | |||
- | Regula este asa: se verifica daca este comanda interna, daca nu, se presupune ca este o comanda externa. | ||
- | </note> | ||
- | |||
- | Shell-ul trebuie să suporte următorii operatori de execuție: | ||
- | |||
- | *operatorul de secvențiere '';'' | ||
- | *va fi folosit pentru a executa comenzile "pe rând"; | ||
- | *de exemplu, ''expr1; expr2'' va avea ca efect mai întâi execuția comenzilor ''expr1'' și, după terminarea execuției acestora, execuția comenzilor ''expr2''; | ||
- | *operatorul de paralelism ''&'' | ||
- | *va fi folosit pentru a executa comenzile în paralel; | ||
- | *de exemplu, ''expr1 & expr2'' va avea ca efect execuția comenzilor ''expr1'' și a comenzilor ''expr2'' în paralel; | ||
- | *în implementare **NU** aveți voie să vă reapelați singuri executabilul. <code>execv("./my_homework", "command");</code> | ||
- | *operatorii de execuție condiționată ''&&'' și ''||'' | ||
- | *vor fi folosiți pentru a executa comenzile în funcție de codul de eroare; | ||
- | *''expr1 && expr2'' va avea ca efect execuția comenzilor ''expr2'' doar în cazul în care comenzile ''expr1'' au ca rezultat un cod de eroare ''0''; | ||
- | *''expr1 || expr2'' va avea ca efect execuția comenzilor ''expr2'' doar în cazul în care comenzile ''expr1'' au ca rezultat un cod de eroare diferit de zero. | ||
- | * operatorul pipe ''|'' este interpus intre doua comenzi. Efectul este redirectionarea a ceea ce scrie pe ecran primul proces | ||
- | spre ceea ce citeste de la tastatura al doilea proces. De exemplu, ''expr1 | expr2'' va avea ca efect execuția comezilor ''expr1'' cu stdout-ul redirectat în stdin-ul comenzilor ''expr2''; | ||
- | |||
- | |||
- | Prioritatea operatorilor de execuție este, de la cel mai prioritar la cel mai puțin prioritar: | ||
- | |||
- | - operatorul pipe | ||
- | - operatorii de execuție condiționată | ||
- | - operatorul de paralelism | ||
- | - operatorul de secvențiere | ||
- | |||
- | Shell-ul trebuie, de asemenea, să suporte și următorii operatori de redirectare: | ||
- | |||
- | *''< nume_fisier'' pentru redirectarea intrării standard din fișierul ''nume_fisier''; | ||
- | *''> nume_fiser'' pentru redirectarea ieșirii standard în fișierul ''nume_fisier''; | ||
- | *''2> nume_fisier'' pentru redirectarea ieșirii de eroare standard în fișierul ''nume_fisier''; | ||
- | *''&> nume_fisier'' pentru redirectarea ieșirii standard și ieșirii de eroare standard în fișierul ''nume_fisier''; | ||
- | *''%%>>%% nume_fisier'' pentru redirectarea ieșirii standard în fișierul ''nume_fisier'' în modul //append//; | ||
- | *''2%%>>%% nume_fisier'' pentru redirectarea ieșirii de eroare standard în fișierul ''nume_fisier'' în modul //append//. | ||
- | |||
- | În fine, shell-ul trebuie să suporte următoarele comenzi interne: | ||
- | |||
- | *''exit'' și ''quit'' pentru terminarea shell-ului | ||
- | *''cd director'' pentru schimbarea directorului curent | ||
- | * **ATENȚIE**: Mini-shell-ul trebuie să funcționeze în continuare la introducerea comenzii ''cd'' fără parametru. Nu se impune implementarea comportamentului din ''bash'' (schimbarea directorului curent cu directorul //home// al utilizatorului curent) și nici o valoare de exit pentru acest scenariu (practic, ''cd'' fără parametru poate să nu facă nimic, dar să nu rămână cu comportament nedefinit care să ducă la erori). | ||
- | |||
- | Shell-ul trebuie să suporte subcomenzi: | ||
- | *formatul de utilizare este ''comanda $(comanda sau lista comenzi)'' | ||
- | *pentru acestea, se va executa tot ce se gaseste in paranteze si rezultatul se va inlocui in lista de comenzi | ||
- | ==== Precizări generale ==== | ||
- | |||
- | *Pentru a simplifica implementarea temei, puteți folosi [[https://github.com/UPB-FILS/sde/blob/master/devoir/devoir3/parse.py | parserul]] implementat de noi. Pentru detalii despre parser, citiți fișierul ''README'' din arhivă. Exemplu de utilizare a parserului găsiți în sursa ''cmd.py'', care poate fi folosită ca schelet pentru temă. | ||
- | *Promptul afișat de shell este impus pentru a facilita testarea automată și este \$ (adică se va afișa caracterul $ urmat de un spațiu). | ||
- | *Numele fișierului principal din temă trebuie să fie ''cmd.py''. | ||
- | |||
- | ==== Sugestii de rezolvare ==== | ||
- | Tema este relativ complexa fata de cea anterioara. Un sablon pentru inceperea temei este disponibil in [[https://github.com/upb-fils/sde|repository]] in directorul //tema3//. | ||
- | |||
- | Recomandăm rezolvarea și testarea din aproape în aproape a temei, după pași: | ||
- | |||
- | - rularea de comenzi simple (''ls'', ''ls -l'') | ||
- | - rularea de comenzi interne (''cd'', ''exit'', ''quit'') | ||
- | - implementarea redirectărilor (operatorii ''<'', ''>'', ''2>'', ''&>'', ''%%>>%%'', ''2%%>>%%'') | ||
- | - secvențierea comenzilor (operatorii ''&&'', ''||'', '';'') | ||
- | - implementarea operatorilor ''&'' (paralel) | ||
- | - ''|'' | ||
- | |||
- | *Aveți mai jos câteva exemple de comenzi și rezultatul generat de acestea: | ||
- | <code bash> | ||
- | $ ls | ||
- | Makefile README.checker mini-shell mini-shell.o parser | ||
- | Makefile.checker inputs mini-shell.c outputs tags | ||
- | |||
- | $ cat /etc/services | grep telnet | ||
- | telnet 23/tcp | ||
- | rtelnet 107/tcp # Remote Telnet | ||
- | rtelnet 107/udp | ||
- | telnets 992/tcp # Telnet over SSL | ||
- | telnets 992/udp | ||
- | tfido 60177/tcp # fidonet EMSI over telnet | ||
- | |||
- | $ uname -a ; ps | ||
- | Linux bogdan-desktop 2.6.31-19-generic #56-Ubuntu SMP Thu Jan 28 02:39:34 UTC 2010 x86_64 GNU/Linux | ||
- | PID TTY TIME CMD | ||
- | 6078 pts/0 00:00:00 bash | ||
- | 6190 pts/0 00:00:00 mini-shell | ||
- | 6200 pts/0 00:00:00 ps | ||
- | |||
- | $ date && sleep 1 ; echo date | ||
- | Mon Feb 8 13:40:25 EET 2010 | ||
- | date | ||
- | |||
- | $ date && sleep 1; date | ||
- | Mon Feb 8 13:40:49 EET 2010 | ||
- | Mon Feb 8 13:40:50 EET 2010 | ||
- | |||
- | $ true && date | ||
- | Mon Feb 8 13:41:16 EET 2010 | ||
- | |||
- | $ false && cat mini-shell.c | ||
- | |||
- | $ false || date | ||
- | Mon Feb 8 13:42:36 EET 2010 | ||
- | |||
- | $ cat /et/services | ||
- | cat: /et/services: No such file or directory | ||
- | |||
- | $ gcc > tmp; echo sep; cat tmp | ||
- | gcc: no input files | ||
- | sep | ||
- | |||
- | $ strace -e trace=read ls 2> strace.out | ||
- | Makefile README.checker mini-shell mini-shell.o parser tags | ||
- | Makefile.checker inputs mini-shell.c outputs strace.out tmp | ||
- | |||
- | $ head -1 strace.out | ||
- | read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@#\0\0\0\0\0\0@"..., 832) = 832 | ||
- | |||
- | $ pwd; cd Teme; pwd | ||
- | /home/bogdan/Documents/SO/Solutii | ||
- | /home/bogdan/Documents/SO/Solutii/Teme | ||
- | |||
- | |||
- | > exit</code> | ||
- | |||
- | ===== Materiale ajutătoare ===== | ||
- | Cursuri utile: | ||
- | *[[sde:cursuri:01]] | ||
- | *[[sde:cursuri:02]] | ||
- | *[[sde:cursuri:03]] | ||
- | *[[sde:cursuri:04]] | ||
- | *[[sde:cursuri:05]] | ||
- | |||
- | Laboratoare utile: | ||
- | *[[sde:laboratoare:01]] | ||
- | *[[sde:laboratoare:02_ro]] | ||
- | *[[sde:laboratoare:03_ro]] | ||
- | *[[sde:laboratoare:04_ro]] | ||
- | *[[sde:laboratoare:05_ro]] | ||
- | |||
- | Resurse: | ||
- | * Parserul pentru comenzi, sablonul de cod și testele sunt disponibile în directorul [[https://github.com/upb-fils/sde/tree/master/tema3| tema3]] din [[https://github.com/upb-fils/sde|repo-ul de pe Github]]. | ||
- | |||
- | |||
- | ===== Parcurgerea linii de comanda ===== | ||
- | Pentru parcurgerea linii de comanda, am scris noi deja un parser (parser.py) pe care il puteti folosi. | ||
- | Incepeti tema in fisierul ''cmd.py'' aflat in sablon. | ||
- | |||
- | Pentru a vizualiza cum arata structura de date primita de la parser, rulati scriptul din cmd.py după care introduceți o comandă de la tastatură. | ||
- | |||
- | <note warning> | ||
- | Pentru a putea rula fișierul cmd.py, trebuie să instalați biblioteca bashlex (''pip3 install bashlex %%--%%target=.''). | ||
- | </note> | ||
- | <code bash> | ||
- | $ pip3 install bashlex --target=. | ||
- | $ python3 cmd.py | ||
- | |||
- | $ ls | ||
- | ls | ||
- | {'op': 4, 'com1': None, 'com2': None, 'commands': [<parse.SimpleCommand object at 0x100b4bfd0>], 'input': None, 'output': None, 'err': None, 'append_err': False, 'append_out': False} | ||
- | commands | ||
- | ls | ||
- | </code> | ||
- | ==== Structura intoarsa in cmd.py ==== | ||
- | Prin apelarea parse.parse(line), se va intoarce un obiect de tipul **Command**. | ||
- | === Clasa Command === | ||
- | Proprietati: | ||
- | * op - tipul de operatie al comenzii (vezi tipurile existente mai jos) | ||
- | * com1 - contine un obiect de tip Command, prima comanda din lista, daca op este OP_NONE, com1 va fi egal cu None | ||
- | * com2 - contine un obiect de tip Command, a doua comanda din lista, daca op este OP_NONE, com2 va fi egal cu None | ||
- | * commands - contine lista de comenzi si argumente (doar daca op este OP_NONE), daca unul din argumente este de forma ''$(cmd_list)'', elementul va fi de tipul Command, in caz contrar, elementul va fi de tipul SimpleCommand | ||
- | <note info> | ||
- | Pentru a verifica tipul unui obiect, folositi structura **isinstance (obj, class)**. | ||
- | </note> | ||
- | * input - contine fisierul de input, daca intrarea este redirectata (''<'') | ||
- | * output - contine fisierul de output, daca iesirea standard este redirectata (''>'', ''>>'') | ||
- | * err - contine fisierul de error_output, daca iesirea de eroare este redirectata (''2>'', ''2>>'', ''&>'', ''&>>'') | ||
- | * append_err - are valoarea True daca iesirea de eroare face append (''2>>'', ''&>>'') | ||
- | * append_out - are valoarea True daca iesirea face append (''>>'', ''&>>'') | ||
- | |||
- | ===Clasa SimpleCommand=== | ||
- | Obiectul de tip SimpleCommand este folosit in cadrul comenzilor cu op egal OP_NONE (comanda simpla). Acestea se gasesc in lista **commands** si sunt fie comenzi, fie parametrii unor comenzi. | ||
- | |||
- | Proprietati: | ||
- | * word - textul efectiv al comenzii sau al parametrului | ||
- | |||
- | ===Tipurile de operatii=== | ||
- | Modulul **parse** expune urmatoarele tipuri de operatii (valoarea lui command.op): | ||
- | |||
- | * OP_CONDITIONAL_NZERO - operatia este de tipul ('' cmd1 && cmd2'') | ||
- | * OP_CONDITIONAL_ZERO - operatia este de tipul (''cmd1 || cmd2'') | ||
- | * OP_SEQUENTIAL - operatia este de tipul (''cmd1 ; cmd2'') | ||
- | * OP_PARALLEL - operatia este de tipul (''cmd1 & cmd2'') | ||
- | * OP_NONE - operatia este de tipul (''comanda parametrii'') | ||
- | * OP_PIPE - operatia este de tipul (''cmd1 | cmd2'') | ||
- | |||
- | ===== Testarea locala a temei ===== | ||
- | |||
- | Pentru a testa tema local, va recomandam ca prima data sa rulati comanda ''make -f Makefile.checker'' in directorul devoir3. Astfel se vor instala toate modulele necesare pentru rularea fisierului cmd.py. In continuare, puteti rula tema folosind ''python3 cmd.py'', iar in directorul verify veti gasi toate comenzile pe care tema trebuie sa le ruleze. | ||
- | |||
- | ===== FAQ ===== | ||
- | |||
- | ***Q:** Tema 3 se poate face în Python 2? | ||
- | ***A:** Nu. | ||
- | |||
- | ***Q:** Trebuie optimizat numărul de fork-uri? Spre exemplu, în cazul comenzii ''a|b|c'' trebuie sa am 3 forkuri sau pot să am 4 sau 5? | ||
- | ***A:** Nu este obligatoriu să optimizați numărul de fork-uri. Totuși, în general este bine să aveți în vedere eficientizarea consumului de resurse. | ||
- | |||
- | ***Q:** Shell-ul trebuie să se comporte ca un shell adevărat (sh, bash) în situația ... ? | ||
- | ***A:** Funcționalitatea minimă necesară este cea din enunțul temei. Daca implementați ceva în plus, precizați în README. Exemple de funcționalitate care nu este cerută: updatarea unor variabile de mediu (gen ''$OLDPWD'' și ''$PWD''), history, multe altele ... (vezi [[http://linux.die.net/man/1/bash | man bash]] pentru o idee despre funcționalitatea unui shell complet :-) ) | ||
- | |||
- | ***Q:** Am voie să nu folosesc parserul din enunț dacă doresc să scriu eu altul echivalent? | ||
- | ***A:** Da. | ||
- | |||
- | ***Q:** Avem voie sa folosim: <code> | ||
- | args = ["/bin/bash", "-c", command] | ||
- | os.execv(args[0], args); | ||
- | </code> | ||
- | ***A:** Nu. | ||
- | |||
- | ***Q:** Am voie să fac ''os.execv'' pe tema mea pentru a executa o parte din arbore independent? | ||
- | ***A:** Nu. | ||
- | |||
- | |||
- | ===== Trimiterea temei ===== | ||
- | Tema se va incarca pe [[https://vmchecker.cs.pub.ro|vmchecker]]. Logati-va pe site cu folosind utilizatorul de pe moodle, selectati cursul //Systemes d'Explotation (FILS)// si incarcati [[#arhiva-temei|arhiva temei]]. | ||
- | |||
- | ==== Readme ==== | ||
- | Fisierul readme are urmatorul format: | ||
- | |||
- | <code> | ||
- | Numele vostru intreg | ||
- | Grupa | ||
- | |||
- | Descrierea rezolvarii temei, de ce ati ales anumite solutii, etc. | ||
- | </code> | ||
- | |||
- | |||
- | ==== Arhiva temei ==== | ||
- | Pentru a incarca tema, urmariti pasii: | ||
- | |||
- | - Creati o arhiva zip (nu rar, ace, 7zip sau alt format) care sa contina: | ||
- | * toate fisierele Python (*.py) | ||
- | * fisierul principal cu numele cmd.py | ||
- | * fisierul Readme | ||
- | - logati-va pe [[https://vmchecker.cs.pub.ro|vmchecker]] | ||
- | - selectati cursul //Systemes d'Explotation(FILS)// | ||
- | - selectati //3. Mini-Shell// | ||
- | - incarcati arhiva | ||
- | |||
- | |||
- | <note> | ||
- | Arhiva trebuie sa contina toate fisierele (principale) in radacina, nu in subdirectoare. NU arhivati directorul temei, arhivati DIRECT fisierele. | ||
- | |||
- | NU includeti directoarele specifice bibliotecii bashlex (__pycache__, bashlex, bashlex-0.14.dist-info). | ||
- | </note> | ||
- | |||
- | Dupa ce incarcati arhiva, vmchecker va rula: | ||
- | |||
- | <code bash> | ||
- | unzip archive.zip homework | ||
- | cd homework | ||
- | make -f Makefile.checker | ||
- | </code> | ||
- | |||
- | |||
- | |||
- | |||