Perl:使用 IPC::Run 进行 I/O 重定向

Posted

技术标签:

【中文标题】Perl:使用 IPC::Run 进行 I/O 重定向【英文标题】:Perl: I/O Redirection with IPC::Run 【发布时间】:2014-01-15 04:30:53 【问题描述】:

目前使用IPC::Run 来模仿以下内容对我来说并没有产生预期的效果。不幸的是,我对使用IPC::Run 的 I/) 重定向不够熟悉,无法自行解决,我需要使用 SO 的强大知识库

我模仿的命令

echo | openssl s_client -connect google.com:443 2>/dev/null |openssl x509

这将显示从带有openssl 的远程服务器检索到的 SSL 证书。它正常工作的关键是stderr 到/dev/null 的2>/dev/null 泵,因为openssl 将使用stderr 输出附加信息(不是真正的错误),没有这个命令将通过管道传送到openssl x509将失败。

这就是IPC::Run 的用武之地。我需要使用IPC::Run 在perl 中使用openssl 的这个功能,因为这是我所有其他功能目前正在使用的功能。不幸的是,使用IPC::Run 以我执行shell 重定向的方式(例如2>/dev/null)不起作用,因为没有调用shell,运行命令并添加2>/dev/null 只会将其作为参数附加到openssl打电话。

目前我有以下内容,没有讨厌的stderr 问题。也没有同意openssl命令压制它。

use IPC::Run qw( run );    
my ( $out, $err );
    my @cmd  = qw(echo);                                            
    my @cmd2 = qw(openssl s_client -connect google.com:443:443);     
    my @cmd3 = qw(openssl x509);                                   
    run \@cmd, "|", \@cmd2, "|", \@cmd3, \$out, \$err;                        
    if ( $err ne '' )                                               
        print $err;
    
    else 
        print "$out\n";
    

所以基本上我需要为 @cmd2 丢弃 stderr,这通常是用的,

run \@cmd, \$in, \$out, \undef;

但与 |为@cmd3 显示为stdin 我无法从@cmd2 重定向stderr,因为stderr 的描述符在stdout 之后。我认为必须有一种方法可以在两个管道之间使用此模块来抑制“stderr”,但我还没有弄清楚,并且对 I/O 操作的熟悉程度不足以快速获得这一点。有没有人从经验中得到这样做的建议?

【问题讨论】:

【参考方案1】:

不需要“回声”。如果您只想关闭由 s_client 打开的连接,请使用已关闭的标准输入。 同样在您的示例中,您连接到 google.com:443:443,这可能是 :443 太多。 以下对我有用

use IPC::Run 'run';

my @cmd1 = qw(openssl s_client -connect google.com:443);
my @cmd2 = qw(openssl x509);

my $stdout = my $stderr = '';
run \@cmd1, '<', \undef, '|', \@cmd2, '2>', \$stderr, '>', \$stdout;
print $stdout;

【讨论】:

以上是关于Perl:使用 IPC::Run 进行 I/O 重定向的主要内容,如果未能解决你的问题,请参考以下文章

Perl IPC::Run 附加输出并解析标准错误,同时将其保存在一批文件中

带有 IPC::Run 的 Perl 命令执行器

使用重定向 I/O 与子进程通信时出现死锁

linux基础--I/O重定向

如何使用 IPC::Run 回答 rsync 密码提示?

从 git 捕获 STDOUT/STDERR