Toon posts:

[bash programming] File descriptors

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hoi allemaal,

ik heb een bash vraagje:
Hoe kan ik een file descriptor openen die door een childproces kan worden uitgelezen. Bijvoorbeeld:

open descriptor x (dit is de vraag: hoe doe ik dat)

programma 3<&x & (dit programma leest nu van file descriptor 3 data, die het parent proces naar zijn descriptor x gaat schrijven)

het childproces draait nu rustig verder, ondertussen doet het hoofdprog op gezette tijden:

echo "een datastring" >&x (deze string vindt het child proces nu op zijn input file descr. 3)

Ik wil dit kunnen implementeren zonder named pipes, want de pipeline mag voor geen enkel ander proces zichtbaar zijn. Het childprocess moet gewoon de aanroepende terminal op standaard input hebben, vandaar dat ik het via een andere descriptor wil connecten.

Hoe pak ik dit aan? Iets met /dev/fd/[i]n[/n]?

  • Wilke
  • Registratie: December 2000
  • Laatst online: 13:19
Zonder named pipes...hmmmja, natuurlijk met het standaard pipe character (dan is het een unnamed pipe lijkt me).

Ik heb dit even geprobeerd en volgens mij werkt het concept wel:

Triviaal voorbeeld:

code:
1
2
3
4
while true;
  do echo "Een datastring";
  sleep 5;
done | cat -


Dit print elke 5 seconden "Een datastring", zoals je zou verwachten. Het kind-proces draait dus blijkbaar inderdaad gelijktijdig mee op de achtergrond. Dat het ook met wat ingewikkelder dingen werkt kun je zo zien:

code:
1
2
3
4
5
i=0
while true;
  do echo "Dit is wat zooi, ik ben alleen geinteresseerd in dit nummer: $[i++]";
  sleep 1;
done | cut -f 2 -d:


Je hoeft niet te wachten tot de hele while-lus is afgesloten voor er iets verschijnt (een lijst met oplopende nummers, om precies te zijn). Dus zal het inderdaad wel parallel lopen, right? En geen named pipe..... :)

In dit concrete geval lijkt het er trouwens wel op dat het parallele proces steeds 1 'regel' achterloopt, mogelijk omdat 'ie steeds probeert door te lezen tot een volgende line-feed ofzo? Hopelijk vormt dit met jouw 'programma' geen probleem, anders moet je wat explicieter met newlines gaan strooien.

  • Papillon
  • Registratie: Januari 2000
  • Laatst online: 07-05 22:41

Papillon

Spring 's in the Air...

Probeer het dan eens met echo "Een datastring \n"

F u cn rd ths, u mght hv a gd jb n cmptr prgmmng.


Verwijderd

Topicstarter
Tnx voor de reacties. Nou dat werkt uiteraard wel, probleem is alleen dat ik wil dat het childproces zijn standard input gewoon van de terminal blijft krijgen (het gaat nl. om passwords vragen etc.) en dat hij de input dus niet op 0 (stdin) maar bijv. op 3 of hoger binnen krijgt.

Kijk, zoiets werkt bij mij ook:

$ exec 3<tekstfile.txt # opent tekstfile.txt om te lezen vanuit fd 3
$ su -c bash # start een nieuwe instantie van bash als root. (vraagt om password)
# read p <&3 # lees uit de overgeërfde descriptor 3
# echo $p
dit is de eerste regel van het bestand tekstfile.txt
# exit
$ _

Dit is dus wat ik wil, maar nu wil ik niet een tekstfile in &3 pipen, maar data vanuit het programma. Iets als echo "data string" >&3 wil niet. Ik kom er nog niet uit!

Nou heb ik inmiddels ontdekt dat bash ook proces substitution doet (of hoe heet het ook maar):

su -c bash 3< <(commandoreeks die data oplevert)

dit start su, en vervolgens de commandoreeks op de achtergrond. De output daarvan komt beschikbaar op input file descriptor 3 van het gestarte proces. Maar nu ben ik gedwongen om de hele commandoreeks tussen die haken te zetten. Dat kan natuurlijk als ik er een function call van maak. En bash implementeert dit met met /dev/fd/n, of een named pipe als /dev/fd/ niet kan. Nu kan /dev/fd/ volgens mij ten allen tijde op Linux, en dat is ook mijn doel systeem, maar het moet natuurlijk wel veilig zijn; een ander proces mag nimmer in dezelfde file schrijven.

Verwijderd

Topicstarter
Gelukt!!

open 2 files:
$ exec 4> >(while read a; do echo "ontvangen op fd4: $a";done)
$ exec 3< <(i=0;while true;do echo "dit is regel $i";let i++;done)
wordt nu root, stdin blijft braaf aan de terminal hangen
(anders geeft su de foutmelding 'must be run from terminal')

$ su -c bash 3<&3 4>&4
# read p <&3 ; echo $p
dit is regel 0
# echo antwoord >&4
# ontvangen op fd4: antwoord (dit wordt naar de terminal geprint door het subproces achter file descriptor 4)

kortere versie:

$ su -c bash 3< <(i=0;while true;do echo "dit is regel $i";let i++;done) 4> >(while read a; do echo "ontvangen op fd4: $a";done)
(op een regel)

Op deze manier kan je dus een proces via su laten runnen, dat zijn input krijgt via een anonieme pipe vanuit een non-root bash proces.

Mijn doel is een klein root-supproces te runnen wat alleen enkele speciale acties kan doen, en dat via su gestart wordt. De user moet dan het root-password intypen. Het hoofd proces draait als een gewone user en geeft dus opdrachten aan het root proces. Het root proces geeft antwoord terug via fd4.

Als ik nou verder oplettend programmeer zou dit moeten werken (geen deadlocks enz).

Ik hou me aanbevolen voor elegantere oplossingen (liever had ik bijvoorbeeld het su proces als coproces).