Getting STDOUT, STDERR, and response code from external *nix command in perl

后端 未结 4 1493
别跟我提以往
别跟我提以往 2020-11-28 16:26

I want to execute an external command from within my Perl script, putting the output of both stdout and stderr into a $variable of my choice, and to get the com

相关标签:
4条回答
  • 2020-11-28 17:09

    Actually, the proper way to write this is:

    #!/usr/bin/perl
    $cmd = 'lsss';  
    my $out=qx($cmd 2>&1);
    my $r_c=$?;
    print "output was $out\n";
    print "return code = ", $r_c, "\n";
    

    You will get a '0' if no error and '-1' if error.

    0 讨论(0)
  • 2020-11-28 17:14

    This was exactly the challenge that David Golden faced when he wrote Capture::Tiny. I think it will help you do exactly what you need.

    Basic example:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    use Capture::Tiny 'capture';
    
    my ($stdout, $stderr, $return) = capture {
      system( 'echo Hello' );
    };
    
    print "STDOUT: $stdout\n";
    print "STDERR: $stderr\n";
    print "Return: $return\n";
    

    After rereading you might actually want capture_merged to join STDOUT and STDERR into one variable, but the example I gave is nice and general, so I will leave it.

    0 讨论(0)
  • 2020-11-28 17:24

    STDERR is intended to be used for errors or messages that might need to be separated from the STDOUT output stream. Hence, I would not expect any STDERR from the output of a command like less.

    If you want both (or either) stream and the return code, you could do:

    my $out=qx($cmd 2>&1);
    my $r_c=$?
    print "output was $out\n";
    print "return code = ", $r_c == -1 ? $r_c : $r_c>>8, "\n";
    

    If the command isn't executable (perhaps because you meant to use less but wrote lsss instead), the return code will be -1. Otherwise, the correct exit value is the high 8-bits. See system.

    0 讨论(0)
  • 2020-11-28 17:25

    A frequently given answer to this question is to use a command line containing shell type redirection. However, suppose you want to avoid that, and use open() with a command and argument list, so you have to worry less about how a shell might interpret the input (which might be partly made up of user-supplied values). Then without resorting to packages such as IPC::Open3, the following will read both stdout and stderr:

    my ($child_pid, $child_rc);
    
    unless ($child_pid = open(OUTPUT, '-|')) {
      open(STDERR, ">&STDOUT");
      exec('program', 'with', 'arguments');
      die "ERROR: Could not execute program: $!";
    }
    waitpid($child_pid, 0);
    $child_rc = $? >> 8;
    
    while (<OUTPUT>) {
      # Do something with it
    }
    close(OUTPUT);
    
    0 讨论(0)
提交回复
热议问题