PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bidirektionale Pipe: Kommunikation zwischen zwei Programmen über Dateideskriptoren



frank
29-12-2010, 18:26
Hallo, Leute!

Ich würde gerne einen möglichst einfachen Befehl haben, mit Hilfe dessen zwei Programme miteinander kommunizieren können. Ein simples Beispiel sind die nachfolgenden Programme 1 und 2:

#!/usr/bin/awk -f

#BEGIN{
#print 0.3;
#fflush();
#}

{
print $1+1;
fflush();
}

und

#!/usr/bin/awk -f

($1 > 100) {exit 0;}
{
print $1*10;
fflush();
}


Für die, die des awk nicht mächtig sind: Programm 1 liest den ersten Wert einer Zeile ein und gibt Wert+1 aus, Programm 2 gibt Wert*10 aus und bricht bei 100 ab.

Mit Fifos ist das ganz einfach:

mkfifo in
<in ./1.awk | ./2.awk >in &
echo 0.3 > in

Den echo-Befehl kann (sollte) man dabei weglassen, wenn in Programm 1 der BEGIN-Block nicht ausgeklammert ist. Die Kommunikation ist dann

0.3
1.3
13
14
140
141


Soweit, so gut. Meine Frage ist nun, wie man das Ganze ohne so eine temporäre Fifodatei hinbekommt. Mein Ansatz war

exec 3<>/dev/null
<&3 ./1.awk | ./2.awk >&3

Hier ist der BEGIN-Block also eingeklammert. Aber es klappt so oder so nicht. Hat da jemand eine schöne Lösung parat? Geht’s vielleicht auch mit den Standarddeskriptoren 0 und 1? Und kann man die Kommunikation von außen vielleicht so anstoßen wie im obigen Fifo-Beispiel?

Eigentlich kann das doch nicht so schwer sein, aber ich habe schon viel im Netz gesucht …

Dann noch einen guten Rutsch,

Frank

frank
04-01-2011, 16:35
Hallo und Frohes Neues!

Vorerst kann ich eine Teillösung anbieten. Zunächst einmal beschränke ich mich auf eine Vereinfachung, nämlich folgendes Programm prog.awk:

#!/usr/bin/awk -f

#BEGIN{
#print 3;
#fflush();
#}

($1 > 10) {exit 0;}
{
print $1+1;
fflush();
}
zusammen mit der Aufgabenstellung, dass das Programm mit sich selbst kommunizieren soll.

Die Lösung lautet dann

echo 3 | ./prog.awk >/dev/stdin
und mit aktivem Begin-Block

: | ./prog.awk >/dev/stdin

Es bleibt nur noch eine Frage: Wie kann ich einen anderen Filedeskriptor verwenden? Im meinem Beispiel ist das ja praktisch die 0, aber dann bekomme ich Probleme mit dem tee-Befehl. Oder gibt es einen anderen Weg des Loggings, ohne dabei etwas an prog.awk zu ändern?

Und auch mit zwei Programmen klappt es nicht: Man könnte diese mit
{ prog1 | prog2; } sozusagen zu einem zusammenfassen, was aber nicht funktioniert („bash: /dev/stdin: Text file busy“). Auch runde statt eckige Klammern (erzeugen intern eine eigene Subshell) führen zu diesem Fehler.

Hat nicht doch jemand vielleicht eine Idee?