2010-05-27 2 views
1

CORE::systemqx 연산자에서 추상화하는 System :: Wrapper 모듈을 작성하고 있습니다. 나는 메서드를 사용하여 command1의 출력을 command2의 입력에 연결하려고 시도합니다. 명명 된 파이프를 사용하여 몇 가지 진전을 이루었지만 POSIX::mkfifo은 플랫폼 간 호환이 아닙니다.크로스 플랫폼 방식으로 두 개의 Perl CORE :: 시스템 명령을 파이프하는 방법은 무엇입니까?

package main; 

my $obj1 = System::Wrapper->new(
    interpreter => 'perl', 
    arguments => [-pe => q{''}], 
    input  => ['input.txt'], 
    description => 'Concatenate input.txt to STDOUT', 
); 

my $obj2 = System::Wrapper->new(
    interpreter => 'perl', 
    arguments => [-pe => q{'$_ = reverse $_}'}], 
    description => 'Reverse lines of input input', 
    output  => { '>' => 'output' }, 
); 

$obj1->serial($obj2); 


package System::Wrapper; 

#... 

sub serial { 
    my ($self, @commands) = @_; 

    eval { 
     require POSIX; POSIX->import(); 
     require threads; 
    }; 

    my $tmp_dir = File::Spec->tmpdir(); 

    my $last = $self; 

    my @threads; 

    push @commands, $self; 

    for my $command (@commands) { 

     croak sprintf 
     "%s::serial: type of args to serial must be '%s', not '%s'", 
     ref $self, ref $self, ref $command || $command 
     unless ref $command eq ref $self; 

     my $named_pipe = File::Spec->catfile($tmp_dir, int \$command); 

     POSIX::mkfifo($named_pipe, 0777) 
      or croak sprintf 
      "%s::serial: couldn't create named pipe %s: %s", 
      ref $self, $named_pipe, $!; 

     $last->output({ '>' => $named_pipe }); 
     $command->input($named_pipe); 

     push @threads, threads->new(sub{ $last->run }); 
     $last = $command; 
    } 

    $_->join for @threads; 
} 

#... 

내 특정 질문 :

  1. 입니다 POSIX::mkfifo에 대한 대안이 여기

    은 (기본적으로 system를 호출 하단에있는 run 방법) 지금까지이 무엇의 일부 크로스 플랫폼? Win32 명명 된 파이프는 작동하지 않습니다. 일반 파일로 열 수 없으며, 소켓을 사용하지 않는 이유도 마찬가지입니다.

    2. 위의 방법은 효과가 없습니다. 두 스레드가 올바르게 생성되지만 아무 것도 파이프를 통해 이동하지 않습니다. 파이프 교착 상태 또는 출력 버퍼링과 관련이 있다고 생각합니다. 나를 없애 버리는 이유는 실제 쉘에서 두 명령을 실행할 때 모든 것이 예상대로 작동한다는 것입니다.

포인트 2가 해결됩니다. a -p fifo 파일 테스트가 올바른 파일을 테스트하지 않았습니다.

답변

1

관심 분야로, 왜 FIFO가 필요합니까? 정규 파이프를 설정하지 못했습니다 (예 : pipe?). 왜 더 많이 사용할 수있을 때 스레드를 사용해야합니까? fork?

실제로 CPAN 모듈을 사용하여 대부분의 작업을 수행 할 수 있습니다. IPC::Run 예 :

use IPC::Run qw(run); 
run ['perl', '-pe', ''], '<', 'input.txt', '|', ['perl', '-pe', '$_ = reverse $_}'], '>', 'output'; 

...은 Linux 또는 Windows에서 예상대로 작동해야합니다.

+0

프로그램이 의미있는 출력을 STDOUT으로 출력하거나 STDIN에서 읽을 수 있다고 보장 할 수 없기 때문에 일반 파이프 나 IPC :: Run을 사용할 수 없습니다. 어떤 프로그램은 입력 또는 출력 파일을 인수로 설정해야 할 수도 있고 그렇지 않으면 죽어 갈 수도 있습니다. 'fork'와'threads'는'fork '가 실제로는 창문 아래에서 덜 강력하다는 인상하에 있습니다. 그러나 내가 포크를 통해 스레드를 사용하고있는 진짜 이유는 없습니다. –

관련 문제