如何从使用su -c的管道中执行的命令获取Perl中的STDERR [英] How to get STDERR in Perl from a command executed in pipe with su -c

查看:198
本文介绍了如何从使用su -c的管道中执行的命令获取Perl中的STDERR的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 我的$ command = qq我试图捕获作为不同用户执行的命令的输出(sudo su  - < username> -c'/ usr / bin / whatever'); 
我的$ pid = open $ cmdOutput, - |,$ command;

如何捕获 / usr / bin / code>?



我尝试过

  $ pid =打开$ cmdOutput, -  |,$ command ||死了出了问题:$!; 

但它看起来像是捕获可能的打开本身的错误。



我也尝试过

  my $ command = qq(sudo su  - < username> -c'/ usr / bin / whatever'2> /tmp/error.message); 

这将重定向到文件,我可以稍后解析,但我想要一些更直接



另外,我只想使用核心模块。

解决方案

p>完全覆盖 在perlfaq8 。由于您正在使用管道打开,所以相关示例是来自核心 open3 .perl.org / IPC / Open3.htmlrel =nofollow noreferrer> IPC :: Open3 模块。



另一个选择是使用 IPC :: Run 来管理你的流程,而 pump 函数将会执行你所需要的。 IPC :: Open3 文档说 IPC :: Run


与您可以根据需要单独或一起操作 STDOUT STDERR 。为了方便和完整的输出捕获,还可以参见 Capture :: Tiny



除了 2>输出重定向,没有更多的基本的方法来管道打开。






如果你不介意混合流或者丢失 STDOUT 另一个选项是

  my $ command =' cmd 2>& 1 1> / dev / null'#删除1> / dev / null以使
我的$ pid =打开我的$ cmdOutput, - |,$ command;

while(< $ cmdOutput>){print}#STDERR only

第一个重定向将 STDERR 流与 STDOUT 合并,这样您就可以得到它们,并且混合(使用 STDOUT 受缓冲影响,因此可能会出错)。第二个重定向发送 STDOUT ,所以使用它只是从句柄中只读取命令的 STDERR p>




问题是使用打开而运行外部命令, d提到规范和简单的 qx backticks )可以以相同的方式使用。它返回 STDOUT ,所以需要如上所述的重定向来获取 STDERR 。为了完整性:

  my $ cmd ='cmd_to_execute'; 
我的$ allout = qx($ cmd 2>& 1); #$ out中的STDOUT和STDERR,或
my $ stderr = qx($ cmd 2>& 1> / dev / null); #只有STDERR
我的$ exit_status = $?

qx 将子进程退出代码(状态)在 $?中。然后可以检查故障模式;请参阅 qx 页面中的摘要或 perlop中的I / O操作符



请注意,以这种方式返回的STDERR 是从命令运行的。如果命令本身无法运行(对于命令名称中的输入错误,或者由于某种原因导致 fork 失败),那么 $?将是 -1 ,错误将在 $!中。


I'm trying to capture the output of the command executed as a different user using:

my $command = qq(sudo su - <username> -c '/usr/bin/whatever');
my $pid = open $cmdOutput, "-|", $command;

How can I capture the STDERR of /usr/bin/whatever?

I tried

$pid = open $cmdOutput, "-|", $command || die " something went wrong: $!";

but it looks like this is capturing the possible errors of "open" itself.

I also tried

my $command = qq(sudo su - <username> -c '/usr/bin/whatever' 2>/tmp/error.message);

which will redirect the STDERR to the file, which I can parse later, but I wanted some more straightforward solution.

Also, I only want to use core modules.

解决方案

This is covered thoroughly in perlfaq8. Since you are using a piped open, the relevant examples are those that go by open3 from the core IPC::Open3 module.

Another option is to use IPC::Run for managing your processes, and the pump function will do what you need. The IPC::Open3 documentation says for IPC::Run

This is a CPAN module that has better error handling and more facilities than Open3.

With either of these you can manipulate STDOUT and STDERR separately or together, as needed. For convenient and complete output capture also see Capture::Tiny.

Other than 2>output redirection, there are no more elementary methods for the piped open.


If you don't mind mixing the streams or losing STDOUT altogether, another option is

my $command = 'cmd 2>&1 1>/dev/null'          # Remove 1>/dev/null to have both
my $pid = open my $cmdOutput, "-|", $command;

while (<$cmdOutput>) { print }                # STDERR only

The first redirection merges STDERR stream with STDOUT so you get them both, and mixed (with STDOUT subject to buffering, thus things may well come out of order). The second redirect sends the STDOUT away so with it in place you read only the command's STDERR from the handle.


The question is about running an external command using open but I'd like to mention that the canonical and simple qx (backticks) can be used in the same way. It returns the STDOUT so redirection just like above is needed to get STDERR. For completeness:

my $cmd = 'cmd_to_execute';
my $allout = qx($cmd 2>&1);              # Both STDOUT and STDERR in $out, or
my $stderr = qx($cmd 2>&1 1>/dev/null);  # Only STDERR
my $exit_status = $?;

The qx puts the child process exit code (status) in $?. This can then be inspected for failure modes; see a summary in the qx page or a very thorough discussion in I/O operators in perlop.

Note that the STDERR returned this way is from the command, if it ran. If the command itself couldn't be run (for a typo in command name, or fork failed for some reason) then $? will be -1 and the error will be in $!.

这篇关于如何从使用su -c的管道中执行的命令获取Perl中的STDERR的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆