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

Updated
Hi,

After consulting the Cookbook (16.7), I've written the following sub.
sub TestRadiusAuth { my $cmd = "$radclient" . " -t $radius_config->{auth_timeout}" . " -r $radius_config->{auth_retries}" . " -i 1 $radius_config->{ip}:$radius_config->{auth_port}" . " auth $radius_config->{secret} <<EOF\n" . "User-Name = \"$test_user\"\n" . "Password = \"$test_pass\"\n" . "NAS-IP-Address = \"$eth0\"\n" . "EOF\n"; my $response; open(CMD, "$cmd 2>&1 |") or die "Could not execute $cmd:$!\n"; while (<CMD>) { chomp(); return (1,$_) if /Session-Timeout/; $response .= $_; } return (0,$response); }
My problem is that the redirection (2>&1) within the piped open does not work as expected. If I deliberately force $cmd to return an error, it still comes to _my_ STDERR, rather than the STDOUT of the CMD filehandle.

I figure that I'm doing something fundamentally stupid, but I can't see it for the life of me.
Would appreciate any advice.

Replies are listed 'Best First'.
Re: Capturing STDERR from a piped open
by McDarren (Abbot) on Aug 13, 2005 at 16:03 UTC
    Just went for a walk and it suddenly hit me....

    I needed to change the following line:

    " auth $radius_config->{secret} <<EOF\n" .

    to:

    " auth $radius_config->{secret} 2>&1 <<EOF\n" .

    All is good now, thanks for the replies :)
Re: Capturing STDERR from a piped open
by tlm (Prior) on Aug 13, 2005 at 15:30 UTC

    FWIW, it works fine for my (on Linux):

    use strict; use warnings; my $cmd = 'ls nonexistent'; open( CMD, "$cmd 2>&1 |" ) or die "Could not execute $cmd: $!\n"; while ( <CMD> ) { chomp; print "<< $_ >>\n"; } __END__ % perl 483558.pl << ls: nonexistent: No such file or directory >>

    the lowliest monk

      Thanks,
      Your example works fine for me too, so I've updated my original post to show the full subroutine.

      $cmd calls radclient to do a test auth against a remote radius server. If I deliberately cause an error, say for example using an incorrect port (causing "radclient: no response from server"), it still comes to _my_ STDERR when I run it.

      Any clues?

        AFAICT, you're trying to feed the external program's stdin through a here-doc, which looks quite hopeless to me. Read what the Good Cookbook has to say about accessing stdin, stdout, and stderr of another process (recipe 16.9, pp. 639-641).

        Update: I guess it was not so hopeless after all. :-/

        the lowliest monk

Re: Capturing STDERR from a piped open
by graff (Chancellor) on Aug 13, 2005 at 15:33 UTC
    That's odd -- it works for me. In a path where "foo.bar" does not exist, running this gives me "I got the error", and nothing else:
    perl -e 'open(C,"ls foo.bar 2>&1 |") or die $!; while(<C>){ print "I got the error\n" if (/No such/) }'
    Maybe you need to be sure about the particular shell that is being invoked when you do the pipeline open? (Mine is /bin/bash; I think C-shells are brain-damaged when it comes to redirecting stderr.)

      On Unix it's always /bin/sh -c.

      the lowliest monk