How to read to and write from a pipe in perl with ActiveState Perl?

别等时光非礼了梦想. 提交于 2020-02-08 03:05:18

问题


This excellent question How to read to and write from a pipe in Perl? provides an excellent answer.

It doesn't work on ActiveState Perl.

The BUGS section of perlfork http://docs.activestate.com/activeperl/5.14/lib/pods/perlfork.html says

In certain cases, the OS-level handles created by the pipe(), socket(), and accept() operators are apparently not duplicated accurately in pseudo-processes. This only happens in some situations, but where it does happen, it may result in deadlocks between the read and write ends of pipe handles, or inability to send or receive data across socket handles.

It is not clear what 'not duplicated accurately' means or if it even applies in this case.

Here is the test program

#! /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:


Option 1

-- if your input perl process is simple enough to put into a one liner

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

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

 # $out is your captured output

-- if your input perl process is complicated, put it into a file

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

Option 2

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


来源:https://stackoverflow.com/questions/33836969/how-to-read-to-and-write-from-a-pipe-in-perl-with-activestate-perl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!