【问题标题】:Capture::Tiny hangs on any sort of prompt/questionCapture::Tiny 挂在任何类型的提示/问题上
【发布时间】:2021-03-24 10:42:08
【问题描述】:

我有执行系统命令的代码:

use strict;
use warnings FATAL => 'all';
use autodie ':default'; # i.e. no "system"
use Devel::Confess 'color';
use Capture::Tiny 'capture';

sub execute {
    my $cmd = shift;
    my ($stdout, $stderr, $exit) = capture {
        system( $cmd )
    };
    
    if ($exit != 0) {
        say "exit = $exit";
        say "STDOUT = $stdout";
        say "STDERR = $stderr";
        die "$cmd failed";
    }
    return 0
}

根据我之前收到的建议

How to get Capture::Tiny to print stderr and stdout upon failure?

但是,当命令的输出给出某种提示或警告时,此子例程不能很好地工作,并且只会永远挂起而不是打印错误消息/提示。

挂起通常发生在各种 LaTeX 命令中,但由于 LaTeX 没有提供非常好的最小工作示例,如果试图删除没有写入权限的文件,也会产生类似的挂起,没有打印/显示错误,

例如chmod a-w tmp

然后调用脚本execute('rm tmp'),这通常会在 CLI 上给出这个问题:rm: remove write-protected regular file 'tmp'?

但只是挂起,输出时没有打印任何内容。

我尝试将system( $cmd ) 更改为 eval { system( $cmd ) },但仍然看不到错误消息。

如何更改上面的子例程,以便在没有写入权限的情况下尝试删除文件时得到提示和错误?

【问题讨论】:

  • 您在输出退出后打印输出。但它不会退出,因为它正在等待输入。所以它完全按照你的要求做。如果您想在程序退出之前打印输出,system 不会成功。我会使用 IPC::Run
  • @ikegami 如何在system 退出之前打印输出?给定当前代码,我没有看到提示
  • 如果你想在程序退出前打印输出,system 就不行了。我会使用 IPC::Run。
  • metacpan.org/pod/IPC::System::Simple 那里没有任何东西可以同时捕获退出代码、标准输出和标准错误,我如何使用 IPC::System::Simple 做到这一点?
  • 不,I::S:S 只提供阻塞等待子进程的函数

标签: perl


【解决方案1】:

有多种方法可以处理这些事情,但每种技术都取决于提示的要求。

  • 有些命令有选项,因此您不必回答问题。例如,rm -f 可以为所欲为。
  • yes 命令是无穷无尽的“是”列表:yes | rm *.txt
  • 同样,如果您知道问题的答案是什么,您可以准备好其输入,some_command < input.txt
  • 在启动命令之前关闭 STDIN 可能会处理某些情况。
  • 有些东西使用环境变量来回答问题,比如PERL_MM_USE_DEFAULT中的ExtUtils::Makemaker
  • Perl 有一些模块可以处理其中一些情况。例如,IPC::Run 允许您将读取和写入混合到一个进程中。 IPC::Open3 等其他选项在这些情况下效果不佳,因为缓冲区要么填满,要么交换阻塞。

可能还有很多其他技术。

【讨论】:

    猜你喜欢
    • 2017-11-03
    • 2016-06-26
    • 2021-05-07
    • 2011-12-11
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多