如何让Capture::Tiny在失败时打印stderr和stdout?

我试图Capture::Tiny在失败时获得命令的输出,

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say';
use Carp 'confess';
use Capture::Tiny 'capture';

sub execute {
    my $cmd = shift;
    my ($stdout, $stderr, $exit) = capture {
      system( $cmd ); # the script dies here
    };
    if ($exit != 0) { # the script should die here
        say "exit = $exit";
        say "STDOUT = $stdout";
        say "STDERR = $stderr";
        confess "$cmd failed";
    }
    say "STDOUT = $stdout";
    say "STDERR = $stderr";
    say "exit code = $exit";
    return 0
}

execute("ls fakedir");

但问题是当我执行脚本时,

con@V:~/Scripts$ perl execute.pl
"ls fakedir" unexpectedly returned exit value 2 at /home/con/perl5/perlbrew/perls/perl-5.32.0/lib/site_perl/5.32.0/Capture/Tiny.pm line 382.

我得到的只是退出值,它没有提供fakedir不存在的有价值的信息。也就是说,我只在脚本成功时得到 STDOUT 和 STDERR。

无论我使用die还是confess遇到相同的问题 -> 脚本不打印输出$stderr并且$stdout

我已经IO::CaptureOutput按照如何在 Perl 中一次性捕获 stderr、stdout 和退出代码的建议进行了尝试?,它做我想要的,但作者https://metacpan.org/pod/IO::CaptureOutput说“维护者不再推荐这个模块 - 请参阅 Capture::Tiny。” 这很奇怪, IO::CaptureOutput 似乎工作得更好!

我怎样才能得到这个脚本一起死$stdout$stderr$exit印有忏悔?

回答

Capture::Tiny工作正常。system正在引发一个错误,就好像use autodie "system"已经打开一样。Capture::Tiny只捕获 STDOUT 和 STDERR,它不会捕获错误。

您必须进行错误处理。您可以使用 eval 块捕获它。

    my ($stdout, $stderr, $exit) = capture {
        eval {
            system( $cmd );
        }
    };
    if (my $e = $@) { # the script should die here
        # Can't get the system exit code from autodie.
        #say "exit = $exit"
        say "STDOUT = $stdout";
        say "STDERR = $stderr";
        confess "$cmd failed";
    }
    else {
        say "STDOUT = $stdout";
        say "STDERR = $stderr";
        say "exit code = $exit";
        return 0;
    }

在这种特定情况下,您已经在做 autodie 所做的事情。关闭捕获块内的 autodie 更简单。

    my ($stdout, $stderr, $exit) = capture {
        no autodie "system";
        system( $cmd );
    };
    if ($exit) {
        say "exit = $exit";
        say "STDOUT = $stdout";
        say "STDERR = $stderr";
        # the script should die here
        confess "$cmd failed";
    }
    else {
        say "STDOUT = $stdout";
        say "STDERR = $stderr";
        say "exit code = $exit";
        return 0;
    }

或者,因为无论如何你都会出错,你可以让 autodie 来做它的事情。

    my ($stdout, $stderr, $exit) = capture {
        system( $cmd );
    };
    say "STDOUT = $stdout";
    say "STDERR = $stderr";
    say "exit code = $exit";


以上是如何让Capture::Tiny在失败时打印stderr和stdout?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>