2018-07-29 9:48 GMT+03:00 tiberiu socaciu <[email protected]>: > Pe 28.07.2018, Nicu <[email protected]> a scris: > > 2018-07-28 1:53 GMT+03:00 MOROIANU Dragos <[email protected]>: > >> [dmoroianu@hpchn01 ~]$ mkfifo t.bc > >> > >> [dmoroianu@hpchn01 ~]$ bc < t.bc > >> acum intr-un alt terminal: > >> [dmoroianu@hpchn01 ~]$ echo "2+3" > t.bc > >> programul afiseaza '5' si iese fara sa mai astepte comanda 'quit'. > >> Cum conving programul sa astepte si alte comenzi si sa iasa doar dupa ce > >> ii trimit 'quit'? > > > > mkfifo t.bc > > bc < t.bc > > ... > > exec 7>t.bc > > echo 2 + 3 >&7 > > echo 4 + 5 >&7 > > > > ideea e sa tii FIFO-ul deschis; altfel, in momentul in care o comanda > > de forma 'foo >out' a fost executata, toti descriptorii care au fost > > deschisi prin redirectionari sint inchisi, indiferent daca 'foo' e un > > proces separat sau o comanda built-in; iar cind capatul de scriere al > > unui FIFO e inchis, procesul din celalt capat primeste un EOF. > > si care e diferenta dintre > si >> in acest caz? > m-ati facut curios cu thread-ul asta si am inceput sa caut putin > despre fd-urile la stdin, stdout, sderr in caz de redirectare >
Foarte multe lucruri scrise pe jumatate in threadul asta. Probabil ca un punct bun de plecare ar fi man 7 pipe. 1. un pipe e un buffer in care un proces scrie si altul citeste, fiecare din ele vede capatul lui ca pe un file descriptor. Procesul care citeste citeste cu blocking[*] reads, astfel incat atunci cand se intoarce cu zero bytes, e tratat ca eof (celalalt a inchis pipe-ul). Procesul care scrie scrie si el cu blocking[*] writes si trece mai departe fie primeste semnalul SIGPIPE si write() se intoarce cu eroarea EPIPE (din cate inteleg amandoua simultan, ca sa poti alege cum le tratezi, nu mi-e foarte clar). 2. In mod traditional, sculele de unix construite in jurul conceptului de "mancam date de la stdin, le transformam cumva si le scriem la stdout" trateaza inchiderea prematura a oricareia din cele doua pipes ca sfarsitul programului (probabil cu diverse chestii de cleanup, gen blocul END la awk, sau mesaje de eroare ca i-a disparut stdout). 3. In shell, simbolurile | , >, <, <(), >(), etc sunt instructiuni pentru shell sa conecteze intre ei sau cu fisiere externe descriptorii proceselor copil. In particular, >> seteaza O_APPEND pe callul de open() din spate, ca sa deruleze fisierul la sfarsit, in rest e fix acelasi lucru ca >. (vezi sectiunea REDIRECTION din man bash, de exemplu). 4. STDIN, STDOUT, STDERR nu sunt "magice" decat prin faptul ca sunt standard (posix? c89? habar n-am, asa au zis inaintasii(TM)). Orice program se asteapta sa aibe fd[0] deschis pentru read si fd[1] si fd[2] deschise pt. write (asa le primesc de la procesul parinte). Poti sa mai ai si altele deschise, dar daca le dai unui proces copil, ala trebuie sa stie cumva sa se uite la ele. Problema cu "tinem in acelasi proces pipe-urile si stdin si stdout la procesul de controlat si scriem chestii pe baza a ce citim" e tricky de rezolvat in bash in principal din cauza faptului ca orice scrieri si citiri trebuie facute in subshellul care are cei doi file descriptori deschisi, iar traditional programarea in bash utilizeaza o gramada de subshelluri, de exemplu daca ai o linie cu | in ea, tot ce e in dreapta pipe-ului e in alt subshell, care nu mai are acces la cei doi file descriptors (si din care nu poti exporta simplu variabile, etc). La fel si cu backticks, etc. E doable, da, dar poate deveni repede complex sa faci chestii in pure bash. Daca programul ala e ceva gandit sa fie utilizat interactiv de un user la terminal, recomandarea mea e in continuare expect. Daca e altceva gandit cu o aplicatie in minte, e plauzibil sa aibe deja un client care vorbeste api-ul ala, e nitel de masochism sa incerci sa-l scrii in bash. [*] in mod normal, poti atat scrie cat si citi din pipe cu O_NONBLOCK, dar din cate imi dau seama, comenzile traditionale unix nu fac asta. Oricum, asta nu schimba cu mult comportamentul, eof e tratat la fel. PS: E posibil sa-mi fi scapat anumite chestii sau sa ma fi exprimat aiurea in unele locuri (nu ma pot lauda ca am facut system programming), dar sunt destul de sigur ca esentialul e corect. As dori sa multumesc sectiunilor 2 si 3 din linux man pages care au facut posibil acest mail. -- P. _______________________________________________ RLUG mailing list [email protected] http://lists.lug.ro/mailman/listinfo/rlug_lists.lug.ro
