本文介绍了如何让 Capture::Tiny 在失败时打印 stderr 和 stdout?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 Capture::Tiny 在失败时获取命令的输出,

I'm trying to go through Capture::Tiny to get output of a command upon failure,

#!/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");

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

but the problem is that when I execute the script,

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.

all I get is the exit value, which doesn't give the valuable information that fakedir doesn't exist. That is, I only get STDOUT and STDERR when the script succeeds.

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

Whether I use die or confess I get the same problem -> the script doesn't print the output $stderr and $stdout

我已经按照 ,它有什么作用我想要,但作者 https://metacpan.org/pod/IO::CaptureOutput 说维护者不再推荐此模块 - 请参阅 Capture::Tiny."这很奇怪,IO::CaptureOutput 似乎工作得更好!

I've tried IO::CaptureOutput as suggested on How do you capture stderr, stdout, and the exit code all at once, in Perl?, which does what I want, but the author https://metacpan.org/pod/IO::CaptureOutput says "This module is no longer recommended by the maintainer - see Capture::Tiny instead." This is strange, IO::CaptureOutput seems to work much better!

我怎样才能让这个脚本在 $stdout$stderr$exit 打印出来后消失?

How can I get this script to die with $stdout, $stderr, and $exit printed with confess?

推荐答案

Capture::Tiny 工作正常.system 正在引发错误,就像 use autodie system" 已开启.Capture::Tiny 只捕获 STDOUT 和 STDERR,不会捕获错误.

Capture::Tiny is working properly. system is raising an error as if use autodie "system" was on. Capture::Tiny only captures STDOUT and STDERR, it does not trap errors.

您必须进行错误处理.你可以用一个 eval 块来捕获它.

You must do the error handling. You can trap it with an eval block.

    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 就更简单了.

In this specific case you're already doing what autodie does. It's simpler to just turn off autodie inside the capture block.

    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 来做它的事情.

Or, since you're going to error anyway, you could let autodie do its thing.

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

这篇关于如何让 Capture::Tiny 在失败时打印 stderr 和 stdout?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 07:32