2018-07-29 11:53 GMT+03:00 Petru Rațiu <[email protected]>: > > > 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. > >
Update: dupa ce am mai dat niste clickuri prin taburile deschise in urma mailului de mai sus, am dat de o jucarie numita pipexec: https://github.com/flonatel/pipexec , pare sa fie impachetata cel putin in Debian deci probabil si pe alte distributii. Asta ar rezolva mai elegant partea de sintaxa a "cum conectez ambele pipe-uri la acelasi proces", dar nu te scapa de cum faci sa nu le pierzi in timp ce te joci cu ce-ai citit. -- P. _______________________________________________ RLUG mailing list [email protected] http://lists.lug.ro/mailman/listinfo/rlug_lists.lug.ro
