如何将一个文件句柄的输出重定向到另一个文件句柄?

3
我希望能在Linux上运行的Perl中设置一个流程管道,由两个部分组成,在不同时间运行。
例如:
启动消费者进程:
open( OUT, "| tar xvf - " ) || die "Failed: tar: $!";

稍后开始生产者进程:

open( IN, "gpg -d $file |" ) || die "Failed: gpg: $!";

但是我需要以某种方式将gpg的输出重定向到tar的输入中。

我可以通过构建一个循环来实现这一点:

while (<IN> ) {
  print OUT;
}

但我想知道是否可以通过重定向将这两个进程粘合在一起。


为什么不使用'or'而不是'||'?'or'的优先级比其他任何运算符都低,所以如果在函数中省略括号,'or'将起到相同的作用,而'||'会开始覆盖函数的参数,这很少是你想要的。此外,对我来说,它看起来更好看。 - Chris Lutz
3个回答

11

添加

pipe( IN, OUT );

就在这两个open语句之前。就是这样!

如果你想要做更复杂的事情,我建议使用IPC :: Run CPAN模块:

http://search.cpan.org/dist/IPC-Run/

它允许您启动进程,将其输入和输出连接在一起,并在链中的任何点添加日志记录或重定向。


这在小型测试脚本中运行得非常好。谢谢。#! /usr/bin/perl -w pipe( IN, OUT ) || die "失败:管道:$!";open( OUT, "| cat -n " ) || die "失败:cat:$!\n"; open( IN, "netstat -n |" ) || die "失败:netstat:$!";close( IN ); close( OUT ); - Martin
我以前在派生进程的父/子通信中使用过管道,但从未用于此。而且它似乎对我不起作用(在Solaris上使用perl 5.8)。我认为open()正在关闭/断开IN/OUT句柄之间的管道。 - runrig

1

我喜欢 Proc::SafeExec,它可以轻松地将进程和文件句柄以几乎任意的方式绑定在一起。这里有一个例子:

use strict;
use warnings;

use Proc::SafeExec;

open(my $ls, "-|", "ls", "-l") or die "Err: $!";
open(my $fh, ">", "tmp.txt") or die "Err: $!";

my $p = Proc::SafeExec->new({
  exec => [qw(sed -e s/a/b/)],
  stdin => $ls,
  stdout => $fh,
});
$p->wait();

在查看IPC::Run之后,它看起来要简单得多…这里是使用IPC::Run的相同示例:
use IPC::Run qw(run);

run [qw(ls -l)], "|", [qw(sed -e s/a/b/)], ">", "tmp.txt";

这些模块看起来很有趣。我下周会仔细研究一下。谢谢。 - Martin
是的,我曾经花费了太长时间手动处理诸如输入/输出重定向、fork/exec、信号处理和PID监控等任务,直到我发现了IPC::Run(以及在较小程度上的Proc::Simple)。 - rjh

1
如果这两个进程完全没有关系,那么请使用先进先出(FIFO)算法。
use POSIX qw(mkfifo);
mkfifo($path, 0700) or die "mkfifo $path failed: $!";

这将在$path处创建一个FIFO。现在让一个进程向该文件写入,另一个进程从中读取。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接