Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP ssh2_exec channel exit status?

Tags:

php

ssh

pecl

Ok, so pecl ssh2 is supposedly a wrapper for libssh2. libssh2 has libssh2_channel_get_exit_status. Is there ANY way to get this information?

I NEED:
-STDOUT
-STDERR
-EXIT STATUS

I get all but exit status. A lot of people throw around phplibsec when ssh is brought up, but I see no way of getting stderr or the channel exit status out of that either:/ Has anybody been able to get all three?

like image 593
Greg Avatar asked May 07 '12 07:05

Greg


2 Answers

So, first thing is first:
NO, they didn't implement libssh2_channel_get_exit_status. Why? Beyond me.

Here is what id did:

$command .= ';echo -e "\n$?"'

I cram a newline and echo of $? onto the end of every command I exec. Rangy? Yes. But it seems to have worked out rather well. I then pull that off into $returnValue and strip all the newlines off the end of stdout. Maybe someday getting the channel's exit status will be supported, and a few years after that it will be in the distro repos. For now, this has been good enough. When your running 30+ remote commands to populate complex remote resources, this is much, much better than setting up and tearing down the ssh session for each command.

like image 52
Greg Avatar answered Nov 03 '22 20:11

Greg


I tried to improve upon Rapzid's answer a bit more. For my purposed I wrapped ssh2 in a php object and implemented these two functions. It allows me to handle the ssh errors using sane exception catching.

function exec( $command )
{
    $result = $this->rawExec( $command.';echo -en "\n$?"' );
    if( ! preg_match( "/^(.*)\n(0|-?[1-9][0-9]*)$/s", $result[0], $matches ) ) {
        throw new RuntimeException( "output didn't contain return status" );
    }
    if( $matches[2] !== "0" ) {
        throw new RuntimeException( $result[1], (int)$matches[2] );
    }
    return $matches[1];
}

function rawExec( $command )
{
    $stream = ssh2_exec( $this->_ssh2, $command );
    $error_stream = ssh2_fetch_stream( $stream, SSH2_STREAM_STDERR );
    stream_set_blocking( $stream, TRUE );
    stream_set_blocking( $error_stream, TRUE );
    $output = stream_get_contents( $stream );
    $error_output = stream_get_contents( $error_stream );
    fclose( $stream );
    fclose( $error_stream );
    return array( $output, $error_output );
}
like image 26
Kendall Hopkins Avatar answered Nov 03 '22 18:11

Kendall Hopkins