2009-03-06 2 views
3

Ich möchte eine Pipeline von Prozessen innerhalb von Perl (unter Linux) einrichten, bestehend aus zwei Teilen, die zu unterschiedlichen Zeiten ausgeführt werden.Wie kann ich die Ausgabe von einem Dateigriff in einen anderen umleiten?

ZB:

den Verbraucher Prozess Start:

open(OUT, "| tar xvf - ") || die "Failed: tar: $!"; 

starten Sie dann viel später den Hersteller Prozess:

open(IN, "gpg -d $file |") || die "Failed: gpg: $!"; 

aber dann irgendwie die Ausgabe von GPG in den Eingang zu Teer umleiten .

Ich kann dies tun, indem eine Schleife bauen:

while (<IN>) { 
    print OUT; 
} 

Aber ich möchte wissen, ob ich irgendwie die beiden Prozesse zusammen mit Umleitung kleben können.

+0

Warum nicht ‚oder‘ statt '||'? 'oder' hat eine niedrigere Priorität als jeder andere Operator. Wenn Sie die Klammern in einer Funktion weglassen, funktioniert 'oder' genauso, während '||' fängt an, die Argumente der Funktion zu überschreiben, was selten das ist, was Sie wollen. Plus, es sieht einfach schöner aus (für mich). –

Antwort

11

pipe(IN, OUT); 

Vor den beiden offenen Aussagen hinzufügen. Das ist es!

Wenn Sie etwas komplizierter machen wollen, würde ich die IPC :: Run CPAN Modul empfehlen:

http://search.cpan.org/dist/IPC-Run/

Es Sie Prozesse starten können, binden ihre Ein- und Ausgänge zusammen, und fügen Sie die Protokollierung oder Umleitung an jedem Punkt in der Kette.

+0

Das funktioniert wunderbar für ein kleines Testskript. Vielen Dank. #!/usr/bin/perl -w Leitung (IN, OUT) || sterben "Failed: pipe: $!"; öffnen (OUT, "| cat -n") || sterben "Failed: cat: $! \ n"; öffnen (IN, "netstat -n |") || sterben "Failed: netstat: $!"; schließen (IN); schließen (OUT); – Martin

+0

Ich habe Pipe zuvor für die Eltern/Kind-Kommunikation für gegabelte Prozesse verwendet, aber niemals dafür. Und es scheint nicht für mich zu funktionieren (Perl 5.8 auf Solaris). Ich denke, die open() 's schließen/trennen das Rohr zwischen den IN/OUT-Griffen. – runrig

1

Wenn die beiden Prozesse völlig unabhängig sind, verwenden Sie einen FIFO.

use POSIX qw(mkfifo); 
mkfifo($path, 0700) or die "mkfifo $path failed: $!"; 

Dies erstellt einen FIFO bei $ path. Jetzt muss ein Prozess in diese Datei schreiben und der andere Prozess daraus lesen.

1

Ich mag Proc::SafeExec es können Sie Prozesse und Dateizugriffe auf fast beliebige Art und Weise miteinander verknüpfen. Hier ein Beispiel:

use strict; 
use warnings; 

use Proc::SafeExec; 

open(my $ls, "-|", "ls", "-l") or die "Err: $!"; 
open(my $fh, ">", "tmp.txt") or die "Err: $!"; 

my $p = Proc::SafeExec->new({ 
    exec => [qw(sed -e s/a/b/)], 
    stdin => $ls, 
    stdout => $fh, 
}); 
$p->wait(); 

Nach einem Blick auf IPC :: Run, es viel einfacher aussieht ... hier ist das gleiche Beispiel IPC :: Run statt:

use IPC::Run qw(run); 

run [qw(ls -l)], "|", [qw(sed -e s/a/b/)], ">", "tmp.txt"; 
+0

Diese Module sehen interessant aus.Ich werde diese nächste Woche sehen. Vielen Dank. – Martin

+0

Ja, ich habe viel zu lange Dinge wie Eingabe/Ausgabeumleitung, Fork/Exec, Signalverarbeitung und PID-Überwachung manuell ausgeführt, bis ich IPC :: Run entdeckte. (Und in geringerem Maße, Proc :: Simple) – rjh

Verwandte Themen