dagolden / Capture-Tiny

(Perl) Capture STDOUT and STDERR from Perl, XS or external programs
http://search.cpan.org/dist/Capture-Tiny/
39 stars 19 forks source link

how to get output for failed, hanging commands? #59

Closed hhg7 closed 3 years ago

hhg7 commented 3 years ago

I have code that executes system commands:

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
}

Based on previous advice that I've received from

https://stackoverflow.com/questions/66016077/how-to-get-capturetiny-to-print-stderr-and-stdout-upon-failure

However, this subroutine doesn't work very well when the output of a command gives some sort of prompt or warning, and just hangs forever instead of printing the error message/prompt.

The hanging normally happens with various LaTeX commands, but because LaTeX doesn't provide for very good minimal working examples, similar hanging with no printed/displayed error is also produced if a file without writing permission is attempted to be deleted,

e.g. chmod a-w tmp

and then calling the script execute('rm tmp') which would ordinarily give this question at the CLI: rm: remove write-protected regular file 'tmp'?

but just hangs with nothing printed at output.

I've tried changing system( $cmd ) to eval { system( $cmd ) } but I still can't see the error messages.

How can I alter the subroutine above so that I get the prompts and errors like when trying to delete a file without write permission?

this question is from a post from StackOverflow: https://stackoverflow.com/questions/66748954/capturetiny-hangs-on-any-sort-of-prompt-question

xdg commented 3 years ago

As someone mentioned on SO, you're asking for something Capture::Tiny can't do. You don't want to see output unless there's an error or a prompt. But there's no way for Capture::Tiny to magically know that there's a prompt versus just a slow-running program. You could try Capture::Tiny's tee function and see if that works well enough for your needs. It's a little fiddly, but you might see output and could see a prompt show up and still have the output captured for some other purpose.