tuckito has asked for the wisdom of the Perl Monks concerning the following question:

Hello lovers of the great perl,
I have a problem with Net::OpenSSH which I don't quite understand.
My code calls a find command on a remote machine where I'm not able to run perl on so I just grab some information and process it somewhere else.
My problem is that capture2() does return undef in stdout when the result of the executed cli command starts with "00" (from my understanding).

$find = "find $args->{'path'}/ -name '$args->{'foo'}.*' -newer ~/start +.txt ! -newer ~/end.txt | xargs grep -vh 'H\\|T' | awk -F, '{ if( \$1 + !~ /\\// & & \$1 >= $args->{'start'} && \$1 < $args->{'end'}){"; for (my $i = 1; $i <= $indices; $i++){ $find .= "if(\$$args->{'index'.$i} ~ /^[0-9]+\$/ && \$$args->{'ind +ex'.$i} >= $args->{'min'.$i} && \$$args->{'index'.$i} <= $args->{'max +'.$i} ){ print \$$args->{'index'.$i} }"; } $find .= "}}' | sort | uniq -c | awk '{print \$2,\",\",\$1}'"; ($edr,$stderr) = $args->{'ssh'}->capture2($find); if($stderr){ print $stderr;} @edr = split /\n/, $edr;
That's the relevant output from debug where the cli command returns "00 , 99":
# io3 mloop, cin: 0, cout: 1, cerr: 0 # io3 fast, cin: 0, cout: 1, cerr: 0 # stdout, bytes read: 8 at offset 0 #> 30 30 20 2c 20 39 39 0a + | 00 , 99. # io3 fast, cin: 0, cout: 1, cerr: 0 # stdout, bytes read: 0 at offset 8 # leaving _io3() # _waitpid(22920) => pid: 22920, rc: Use of uninitialized value $edr in split at /home/bo/scripts/test.pl l +ine 338.
This debug output shows a working example:
# io3 mloop, cin: 0, cout: 1, cerr: 1 # io3 fast, cin: 0, cout: 1, cerr: 1 # stdout, bytes read: 15 at offset 0 #> 39 39 30 31 30 32 20 2c 20 32 30 34 36 32 0a + | 990102 , 20462. # io3 fast, cin: 0, cout: 1, cerr: 1 # stdout, bytes read: 0 at offset 15 # stderr, bytes read: 0 # leaving _io3() # _waitpid(22922) => pid: 22922, rc:
The cli sommand returns "990102 , 20462" and the script runs fine.
I noticed that stderr is missing in the previous debug output. Sometimes the cli comamnd returns more than one line that's why I split $edr into an array.
In the beginning I uses capture() instead of capture2() but I needed the stderr for troubleshooting so I stuck to it.
My understanding of the Net::OpenSSH code is not that good, so I'm asking for help, maybe it is intentionally returning undef. Thank you for your time, tuckito

Replies are listed 'Best First'.
Re: Confused with Net::OpenSSH - capture2()?
by salva (Canon) on Feb 04, 2016 at 10:06 UTC
    The following capture2 call works for me.
    my ($stdout, $stderr) = $ssh->capture2(echo => -n => '00 , 99.')

    It doesn't seem to be have any problem handling output starting by 00.

    Also, as you are not posting the full script, it is difficult to know if the issue may be originating somewhere else.

    Try including the following code just after the capture2 method call and posting here its output:

    use Data::Dumper; print Dumper([$cmd, $edr, $stderr, $?, $ssh->error]);
      You sir are my hero!
      "somewhere else" is the key and I'm embarassed that I spent hours on this error.
      I noticed that I pasted the wrong find command which is related to a different set of files I try to process.
      The files from which I get the string starting with 00 are found by another find command for which I forgot to change the "old" call of capture() to capture2().
      As said before I switched because of the sporadic ssh connection loss (which is out of scope for this "undef" issue).
      But then I forgot that there is a second find/awk command with an additionally condition that works on a subset of files (containing the 00) that "coincidentally" get processed by an additional call of capture() which I forgot to change to capture2().
      Basically the string $edr is empty because capture() is returning an array which I afterwards try to fill with a split on an empty $edr.
      It's always the simplest error that soaks up the most time for troubleshooting :-)