2015-11-20 2 views
0

Cette excellente question How to read to and write from a pipe in Perl? fournit une excellente réponse.Comment lire et écrire depuis un tube en Perl avec ActiveState Perl?

Cela ne fonctionne pas sur ActiveState Perl.

La section BUGS de perlfork http://docs.activestate.com/activeperl/5.14/lib/pods/perlfork.html dit

Dans certains cas, le système d'exploitation au niveau handles par la conduite(), socket() et accept() les opérateurs sont apparemment pas dupliquées avec précision dans les pseudo-processus. Cela ne se produit que dans certaines situations, mais là où cela se produit, il peut en résulter des interblocages entre les extrémités de lecture et d'écriture des poignées ou l'impossibilité d'envoyer ou de recevoir des données entre les poignées de socket.

On ne sait pas exactement ce que signifie «non dupliqué avec précision» ou s'il s'applique même dans ce cas.

Voici le programme de test

#! /usr/bin/env perl 

use strict; 
use warnings; 

my $isActiveStatePerl = 1 ; # defined(&Win32::BuildNumber); 

sub pipeFromFork 
{ 
    return open($_[0], "-|") if (!$isActiveStatePerl); 
    pipe $_[0], my $child or die "cannot create pipe"; 

    printf STDERR "$$: pipe create parent %d child %d\n", fileno($_[0]), fileno($child); 
    my $pid = fork(); 
    die "fork failed: $!" unless defined $pid; 
    if ($pid) {   # parent 
     printf STDERR "$$: fork parent close child %d\n", fileno($child); 
     close $child; 
    } else {   # child 
     open(STDOUT, ">&=", $child) or die "cannot clone child to STDOUT"; 
     printf STDERR "$$: fork child close parent %d stdout %d\n", fileno($_[0]), fileno(STDOUT); 
     close $_[0]; 
    } 
    return $pid; 
} 


my @transform = qw(tr [A-Za-z] [N-ZA-Mn-za-m]); # rot13 
my @inception = (
    "V xabj, Qnq. Lbh jrer qvfnccbvagrq gung V pbhyqa'g or lbh.", 
    "V jnf qvfnccbvagrq gung lbh gevrq.", 
); 

sub snow_fortress { print STDERR "$$: 1 start\n"; print map "$_\n", @inception } 

sub hotel 
{ 
    printf STDERR "$$: 2 start %d\n", fileno(STDIN); 
    # my $pid = open STDIN, "-|"; 
    my $fh; 
    my $pid = pipeFromFork($fh); 
    print STDERR "$$: hotel: pid $pid\n"; 
    defined($pid) or die "$0: fork: $!"; 
    if (0 == $pid) { 
     snow_fortress; 
     print STDERR "$$: 1 exit\n"; 
     exit(0); 
    } 
    open(STDIN, "<&", $fh) or die "cannot clone to STDIN"; 
    printf STDERR "$$: 2 exec %d\n", fileno(STDIN); 
    # print while <STDIN>; 
    exec @transform or die "$0: exec: $!"; 
} 

# my $pid = open my $fh, "-|"; 
my $pid = pipeFromFork(my $fh); 
defined($pid) or die "$0: fork: $!"; 
print STDERR "$$: outer: pid $pid\n"; 

if (0 == $pid) { 
    hotel; 
    print STDERR "$$: 2 exit\n"; 
    exit(0); 
} 

print STDERR "$$: 3 start " . fileno($fh) . "x\n"; 

print while <$fh>; 
print STDERR "$$: 3 end\n"; 
close $fh or warn "$0: close: $!"; 
+1

Quel est le système d'exploitation? Je pense généralement à ActiveState en tant que perl pour Windows, mais je pense à 'tr' comme un utilitaire pour les systèmes Unix-y. – mob

+0

C'est un script Perl à exécuter sur plusieurs plates-formes. ActiveState est le perl fourni sur la plate-forme Windows. tr est un perl intégré, voir perlop. – codeDr

+1

Ensuite, cela n'a pas de sens d'utiliser 'exec' pour invoquer un perl intégré. Voir perlfunc. – mob

Répondre

0

Option 1

- si votre processus de perl d'entrée est assez simple à mettre en une seule ligne

my $cmd = "perl -e ' -- your simple perl -- ' | cmdToExecute"; 

my $out; 
open my $cmdpipe "-|", $cmd; 
while (<$cmdpipe>) { 
    $out .= $_; 
} 

# $out is your captured output 

- si votre processus perl d'entrée est compliqué, mettez-le dans un fichier

my $cmd = "perl compInput.pl | cmdToExecute"; 
# rest as above 

Option 2

- remove ActiveState perl 
- install git for windows and use the perl from it.