Как я могу передать две команды Perl CORE :: system кроссплатформенным способом? - PullRequest
1 голос
/ 28 мая 2010

Я пишу модуль System :: Wrapper, чтобы абстрагироваться от CORE::system и оператора qx. У меня есть метод serial, который пытается подключить вывод команды command1 к входу команды2. Я добился определенного прогресса, используя именованные каналы, но POSIX::mkfifo не является кроссплатформенным.

Вот часть того, что у меня есть (метод run внизу в основном вызывает system):

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, которая является кроссплатформенной? Именованные каналы Win32 не работают, так как вы не можете открыть их как обычные файлы, так же как и сокеты, по тем же причинам.

    2. Выше не совсем работает; две нити появляются правильно, но по трубе ничего не течет. Я полагаю, что это может быть связано с блокировкой канала или буферизацией вывода. Меня отталкивает то, что когда я запускаю эти две команды в реальной оболочке, все работает как положено.

пункт 2 решен; -p Проверка файла fifo не проверяла правильный файл.

1 Ответ

1 голос
/ 28 мая 2010

Из интереса, зачем тебе FIFO? Не могли бы вы просто установить обычный канал (например, с pipe ?) И зачем использовать потоки, когда вы можете использовать гораздо более поддерживаемую fork ?

Фактически, вы могли бы вместо этого использовать модуль CPAN, чтобы выполнять большую часть своей работы за вас. IPC :: Run , например:

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

... должен работать, как вы ожидаете, в Linux или Windows.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...