2010-12-07 9 views
2

Ich habe ein Kommandozeilen-Dienstprogramm von einer dritten Partei (es ist groß und in Java geschrieben), die ich verwendet habe, um mir einige Daten zu verarbeiten. Dieses Dienstprogramm erwartet Informationen in einer Datei mit Zeilenbegrenzung und gibt dann verarbeitete Daten an STDOUT aus.Gibt es eine Möglichkeit, Daten von Perl zu einem Unix Command Line Utility zu leiten

In meinen Testphasen ging es mir gut, etwas Perl zu schreiben, um eine Datei voller Informationen zu erstellen und diese Datei an dieses Drittanbieter-Dienstprogramm zu senden, aber als ich diesen Code in Produktion bringe, würde ich würde es wirklich bevorzugen, Daten direkt an dieses Dienstprogramm zu leiten, anstatt zuerst diese Daten in eine Datei zu schreiben, da dies mir den Aufwand ersparen würde, nicht benötigte Informationen auf die Festplatte zu schreiben. Ich habe vor kurzem in diesem Board gefragt, wie ich das unter Unix machen könnte, habe aber inzwischen erkannt, dass es unglaublich praktisch wäre, es direkt aus einem Perl-Modul heraus zu starten. Vielleicht so etwas wie:

system(bin/someapp do-action --option1 some_value --input $piped_in_data)

Derzeit ich das Dienstprogramm rufen Sie wie folgt vor:

bin/someapp do-action --option1 some_value --input some_file

Im Grunde, was ich will, ist meine Daten alle entweder auf eine Variable zu schreiben oder zu STDOUT und dann um es über einen Systemaufruf im SAME Perl-Skript oder -Modul an die Java-App zu leiten. Das würde meinen Code flüssiger machen. Ohne sie würde ich ein Perl-Skript schreiben müssen, das eine Bash-Datei auf halbem Wege aufruft, die wiederum ein anderes Perl-Skript aufrufen müsste, um die Daten vorzubereiten. Wenn es mir möglich wäre, würde ich liebend gerne den ganzen Weg in Perl bleiben. Irgendwelche Ideen?

+0

Akzeptiert das Tool Daten auf STDIN? – thejh

Antwort

8

Wenn ich Ihre Frage richtig lese, möchten Sie einen Prozess spawnen und in der Lage sein, sowohl auf seine stdin zu schreiben als auch von seiner stdout zu lesen. Wenn das der Fall ist, dann ist IPC::Open2 genau das, was Sie brauchen. (Siehe auch IPC::Open3 Sie müssen auch aus dem Prozess 'stderr lesen.)

Hier ist ein Beispielcode. Ich habe die Bereiche markiert, die Sie ändern müssen.

#!/usr/bin/perl 

use strict; 
use warnings; 

use IPC::Open2; 

# Sample data -- ignore this. 
my @words = qw(the quick brown fox jumped over the lazy dog); 

# Automatically reap child processes. This is important when forking. 
$SIG{'CHLD'} = 'IGNORE'; 

# Spawn the external process here. Change this to the process you need. 
open2(*READER, *WRITER, "wc -c") or die "wc -c: $!"; 

# Fork into a child process. The child process will write the data, while the 
# parent process reads data back from the process. We need to fork in case 
# the process' output buffer fills up and it hangs waiting for someone to read 
# its output. This could cause a deadlock. 
my $pid; 
defined($pid = fork()) or die "fork: $!"; 

if (!$pid) { 
    # This is the child. 

    # Close handle to process' stdout; the child doesn't need it. 
    close READER; 

    # Write out some data. Change this to print out your data. 
    print WRITER $words[rand(@words)], " " for (1..100000); 

    # Then close the handle to the process' stdin. 
    close WRITER; 
    # Terminate the child. 
    exit; 
} 

# Parent closes its handle to the process' stdin immediately! As long as one 
# process has an open handle, the program on the receiving end of the data will 
# never see EOF and may continue waiting. 
close WRITER; 

# Read in data from the process. Change this to whatever you need to do to 
# process the incoming data. 
print "READ: $_" while (<READER>); 

# Close the handle to the process' stdin. After this call, the process should 
# be finished executing and will terminate on its own. 
close READER; 
+2

Diese aktuelle Frage http://stackoverflow.com/questions/4377967/how-can-i-run-a-system-command-and-die-if-any-ything-ist-written-to-stderr zeigt einige Arbeitsbeispiele von IPC :: Open3 – dwarring

+0

Ich denke, das ist genau das, was ich will, aber ich habe einige Probleme herauszufinden, wie man es in meinem Beispiel verwendet. Gibt es eine Chance, dass Sie einen Beispielcode ähnlich dem Beispiel in meinem Beitrag einfügen können? – Eli

+0

@Eli: Ich habe meine Antwort aktualisiert, um einen Beispielcode zur Verfügung zu stellen. – cdhowie

1

Wenn es nur Dateien akzeptiert, lassen Sie es öffnen "/ proc/self/fd/0", die die gleiche wie STDIN ist. Für den Rest siehe cdhowies antwort.

+1

Oder '/ dev/stdin', das ein Symlink zu'/proc/self/fd/0' sein kann. – cdhowie

1

Wenn alles, was Sie tun wollen Pfeifen STDIN die STDOUT aus Ihrem Programm in Ihrem anderen Programm ist, können Sie dies über den Standard-Perl open Befehl tun:

open (CMD, "|$command") or die qq(Couldn't execute $command for piping); 

Dann alles, was Sie tun müssen, um senden Daten auf diesen Befehl ist die print Anweisung:

print CMD $dataToCommand; 

Und Sie Ihre Pfeife schließlich schließen mit der close Aussage:

close (CMD); 

PERL TIPP

Perl hat ein Befehl perldoc aufgerufen, die Sie in der Dokumentation jeder Perl-Funktion oder Perl-Modul auf Ihrem System installiert geben kann.Um mehr Informationen über den open Befehl, geben Sie zu erhalten:

$ perldoc -f open 

Die -f sagt dies eine Funktion Perl ist

Wenn Sie das tun, was cdhowie sagte in seiner Antwort (Sie Laichen ein Prozess, dann Lesen und Schreiben in diesen Prozess), benötigen Sie IPC::Open2. Um Informationen über das IPC::Open2 Modul zu erhalten, geben Sie ein:

$ perldoc IPC::Open2 
Verwandte Themen