MattSizzle
MattSizzle

Reputation: 3175

Perl: I/O Redirection with IPC::Run

Using IPC::Run trying to imitate the following is not producing the desired affect for me at this time. Unfortunately I am not familiar enough with I/) redirection with IPC::Run to solve for myself and I will need to employ the great knowledge-base of SO.

Command I am imitating

echo | openssl s_client -connect google.com:443 2>/dev/null |openssl x509

This will display the SSL certificate retrieved from a remote server with openssl. The key to it working right is the 2>/dev/null pump of stderr to /dev/null as openssl will use stderr to output additional information (not really error) and without this the command being piped into openssl x509 will fail.

Here is where IPC::Run come in. I need to use this functionality of openssl in perl using IPC::Run as that is what all my other functions are using currently. Unfortunately using IPC::Run in the manner in which I do shell redirects such as 2>/dev/null do not work as a shell is not evoked, to run the command and adding 2>/dev/null will simply append that as an argument to the openssl call.

Currently I have the following, which would work without the pesky stderr issue. Also there is no agreement to the openssl command to suppress it.

use IPC::Run qw( run );    
my ( $out, $err );
    my @cmd  = qw(echo);                                            
    my @cmd2 = qw(openssl s_client -connect google.com:443:443);     
    my @cmd3 = qw(openssl x509);                                   
    run \@cmd, "|", \@cmd2, "|", \@cmd3, \$out, \$err;                        
    if ( $err ne '' ) {                                              
        print $err;
    }
    else {
        print "$out\n";
    }

So basically I need to discard stderr for @cmd2 which is typically done with,

run \@cmd, \$in, \$out, \undef;

but with the | present as stdin for @cmd3 I can not redirect stderr from @cmd2 as the descriptors for stderr is after that for stdout. I figure there has to be a way to suppress 'stderr' using this module between two pipe, but I have not figured it out yet, and am not familiar with the I/O operations enough to get this quickly. Anyone got a suggestion for doing this from experience?

Upvotes: 2

Views: 736

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123330

The 'echo' not needed. If you just want to close the connection opened by s_client use a closed stdin. Also in your example you connect to google.com:443:443 which is propable one :443 too much. The following works for me

use IPC::Run 'run';

my @cmd1 = qw(openssl s_client -connect google.com:443);
my @cmd2 = qw(openssl x509);

my $stdout = my $stderr = '';
run \@cmd1, '<', \undef, '|', \@cmd2, '2>', \$stderr, '>', \$stdout;
print $stdout;

Upvotes: 3

Related Questions