This shows you the differences between two versions of the page.
sde:teme:tema_ro_3_python [2020/03/16 17:49] ioana_maria.culic [Arhiva temei] |
— (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: **29 Martie, 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()'', 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 [[#parcurgearea linii de comanda | 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 --target=. bashlex). | ||
- | </note> | ||
- | <code bash> | ||
- | $ pip3 install --target=. bashlex | ||
- | $ 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'') | ||
- | |||
- | ===== 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 | ||
- | python3 cmd.py | ||
- | </code> | ||
- | |||
- | |||
- | |||
- | |||