gpt4 book ai didi

perl - Capture::Tiny 与 Mason 不兼容?

转载 作者:行者123 更新时间:2023-12-04 07:15:08 25 4
gpt4 key购买 nike

作为一般政策,我避免使用 backticks而是依靠 Capture::Tinysystem来电。

my ( $stdout, $stderr, @results ) = capture { system($command) };
但是,我刚刚遇到了 Capture::Tiny 内部的异常。在 HTML::Mason 下使用时我以前没见过的
 Error from open(GLOB(0x555ef4527090), >&-1): Invalid argument at /usr/share/perl5/vendor_perl/Capture/Tiny.pm line 107.
Capture::Tiny::_open(GLOB(0x555ef4527090), ">\\x{26}-1") called at /usr/share/perl5/vendor_perl/Capture/Tiny.pm line 194
Capture::Tiny::_open_std(HASH(0x555ec25b12b8)) called at /usr/share/perl5/vendor_perl/Capture/Tiny.pm line 391
Capture::Tiny::_capture_tee(1, 1, 0, 0, CODE(0x555f05d5ce70)) called at InternalModule.pm line 41
...
InternalModule.pm called at /.../apache/htdocs/autohandler line 84
HTML::Mason::Commands::__ANON__() called at /usr/share/perl5/vendor_perl/HTML/Mason/Component.pm line 135
这是一个遗留系统,所以模块版本有点旧。
  • HTML::Mason 1.56
  • Capture::Tiny 0.44

  • 做一些深入研究 Capture::Tiny显示此方法正在引发异常
    sub _open {
    open $_[0], $_[1] or Carp::confess "Error from open(" . join(q{, }, @_) . "): $!"; # Line 107
    # _debug( "# open " . join( ", " , map { defined $_ ? _name($_) : 'undef' } @_ ) . " as " . fileno( $_[0] ) . "\n" );
    }
    具体来说,调用 _open 的是 STDOUT 的打开。并导致异常:
    # In some cases we open all (prior to forking) and in others we only open
    # the output handles (setting up redirection)
    sub _open_std {
    my ($handles) = @_;
    _open \*STDIN, "<&" . fileno $handles->{stdin} if defined $handles->{stdin};
    _open \*STDOUT, ">&" . fileno $handles->{stdout} if defined $handles->{stdout}; # Line 194
    _open \*STDERR, ">&" . fileno $handles->{stderr} if defined $handles->{stderr};
    }
    我已经尝试本地化 *STDOUT,虽然看起来 Capture::Tiny已经这样做了。
    现在我得出的结论是,我应该采用这样的解决方案
    system("program args 1>program.stdout 2>program.stderr");
    关于 Capture::Tiny 我还有什么遗漏的吗?使其在 Mason 下工作?

    最佳答案

    使用 Capture::Tiny 有一些好处与 system调用反引号

  • 可以更详细地检查和报告错误情况
  • stdout 和 stderr 的单独信息
  • 没有任何内容保存到磁盘(因此有敏感信息暂时在文件系统上的风险)

  • 但是,在这种情况下,我决定编写备份方法以防万一 Capture::Tiny在任何特定环境中都不可用。如果不是,那么我们只需将这些流输出到临时文件并在之后摄取它们。
    # Capture::Tiny has an incompatibility with Mason.  Therefore we simply need to
    # detect if it's safe to use, and if not we should do another mechanism for
    # capturing the results.
    state $is_safe_to_use_capture_tiny = eval {
    capture sub { };
    1;
    };

    my ( $stdout, $stderr, @result );

    if ($is_safe_to_use_capture_tiny) {
    ( $stdout, $stderr, @result ) = capture { system($command) };

    } else {
    # Backup equivalent to Capture::Tiny
    # There is some risk to this approach, because we are choosing to cache
    # the stdout and stderr results to a file temporarily. If these results
    # of the system call include sensitive information, then it would exist on
    # disk momentarily.
    # However, given this is just a backup method that is only needed in
    # the case of system calls under Mason which is front end servers that do not
    # have access to sensitive information, it's an okay sacrifice.

    my $stdout_file = tempfile();
    my $stderr_file = tempfile();

    @result = system(qq{$command 1>$stdout_file 2>$stderr_file});
    $stdout = $stdout_file->exists ? $stdout_file->slurp : '';
    $stderr = $stderr_file->exists ? $stderr_file->slurp : '';
    }

    关于perl - Capture::Tiny 与 Mason 不兼容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68810780/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com