如何以跨平台方式管道传输两个 Perl CORE::system 命令?
Posted
技术标签:
【中文标题】如何以跨平台方式管道传输两个 Perl CORE::system 命令?【英文标题】:How can I pipe two Perl CORE::system commands in a cross-platform way? 【发布时间】:2010-05-27 21:57:34 【问题描述】:我正在编写一个 System::Wrapper 模块来抽象出 CORE::system
和 qx
运算符。我有一个serial
方法,它尝试将command1 的输出连接到command2 的输入。我在使用命名管道方面取得了一些进展,但 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;
#...
我的具体问题:
有没有跨平台的POSIX::mkfifo
的替代品? Win32 命名管道不起作用,因为您不能将它们作为常规文件打开,套接字也不能,出于同样的原因。
2。上面的不太奏效;两个线程正确生成,但没有任何东西流过管道。我想这可能与管道死锁或输出缓冲有关。让我失望的是,当我在实际的 shell 中运行这两个命令时,一切都按预期工作。
第 2 点已解决; -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 上应该可以正常工作。
【讨论】:
我不能使用常规管道,也不能使用 IPC::Run,因为我不能保证程序可以将有意义的输出打印到 STDOUT 或从 STDIN 读取。某些程序可能需要将输入或输出文件设置为参数,否则会死机。关于fork
与threads
,我的印象是fork
实际上在Windows 下不太健壮。但是我没有真正的理由在 fork 上使用线程。以上是关于如何以跨平台方式管道传输两个 Perl CORE::system 命令?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Perl 将输入通过管道传输到 Java 应用程序?
如何在 ASP.NET Core 的 .json 配置文件中以跨平台方式存储文件路径?