2013-08-18 17 views
9

Sto provando a fare in modo che STDOUT/STDERR da un processo figlio di exec torna al genitore tramite una pipe in Perl. Il più vicino che ho visto a quello che voglio fare è a: http://forums.devshed.com/perl-programming-6/exec-and-redirecting-stdout-stderr-168501.htmlreindirizzamento di stdin/stdout dal processo di esecuzione alla pipe in Perl

Il seguente è un esempio ridotto di ciò che sto cercando di fare. Ho anche provato una variante del link qui sopra. Non riesco a vedere cosa sto facendo male ...

#!/usr/bin/env perl 

use strict ; 
use warnings ; 

my $cmd = "/usr/bin/who -a" ; # anything to stdout 

pipe(READER, WRITER) ; 
my $child = fork() ; 
if ($child) { 
    print "I am the parent: My pid = $$ junior = $child\n" ; 
    close(WRITER) ; 
    my @output = <READER> ; 
    print @output ; 
    print "parent is DONE\n" ; 
} else { 
    print "I am the child. My pid = $$\n" ; 

    close(READER) ; 
    close(STDOUT); 
    close(STDERR); 
    *STDOUT = *WRITER ; 
    *STDERR = *WRITER ; 

    print WRITER "XXX ouput before exec....\n" ; 

    exec($cmd) or exit(1) ; 
} 
+2

Potreste essere interessati a [IPC :: Open2] (http://perldoc.perl.org/IPC/Open2.html). – squiguy

risposta

5

Non è possibile reindirizzare i descrittori di file solo con i compiti. Piuttosto è necessario utilizzare open come descritto in perldoc -f open. Nel tuo caso il codice di bambino sarebbe simile a questa:

print "I am the child. My pid = $$\n" ; 

    close(READER) ; 

    open STDOUT, ">&", \*WRITER or die $!; 
    open STDERR, ">&", \*WRITER or die $!; 

    print WRITER "XXX ouput before exec....\n" ; 

    exec($cmd) or exit(1) ; 
4

Slaven Rezic ha la risposta giusta per il motivo per cui il codice non funziona, ma si dovrebbe anche essere a conoscenza di un collegamento che è possibile utilizzare. Lo speciale tubo + forcella open READER, '-|' fa quasi tutto il lavoro di installazione per te, creando un processo figlio con la sua scrittura STDOUT in una pipe che il genitore può leggere con READER. Questo lascia solo il reindirizzamento STDERR che devi fare manualmente.

La versione abbreviata del codice simile a questo:

my $child = open READER, '-|'; 
defined $child or die "pipe/fork: $!\n"; 
if ($child) { 
    print "I am the parent: My pid = $$ junior = $child\n" ; 
    my @output = <READER> ; 
    print @output ; 
    print "parent is DONE\n" ; 
} else { 
    print "I am the child. My pid = $$\n" ; 

    open STDERR, '>&STDOUT'; 

    print "XXX ouput before exec....\n" ; 

    exec($cmd) or exit(1) ; 
} 
0

Questo codice è un altro modo per il tubo del STDOUT e STDERR dal processo figlio.

#!/usr/bin/env perl 
use strict ; 
use warnings; 

my $cmd = "/usr/bin/who -a" ; # anything to stdout 

pipe(READER, WRITER) ; 
my $child = fork() ; 
if ($child) { 
    print "I am the parent: My pid = $$ junior = $child\n" ; 
    close(WRITER) ; 
    my @output = <READER> ; 
    print @output ; 
    print "parent is DONE\n" ; 
} else { 
    print "I am the child. My pid = $$\n" ; 
    close(READER) ; 
    open(STDERR,">&", WRITER) or die "Cannot duplicate STDERR; 
    open(STDOUT,">&", WRITER) or die "cannot duplicate STDOUT"; 

    print WRITER "XXX ouput before exec....\n" ; 

    exec($cmd) or exit(1) ; 

}

Problemi correlati