I've tried that and the problem I have is that this line blocks when there is an error:
$output = stream_get_contents($stream, 1000000);
the script hangs on that line and I never get around to reading the error stream contents. Here is my current script:
<?php
/**
* Script for testing ssh login
*/
if (!extension_loaded("ssh2")) {
die("SSH2 extension not found");
}
require_once "db_bootstrap.php";
require_once EREP_JOOMLA_PATH . "/erp_php/includes/classes/EREPImageDaemonServer.php";
define("SSH_COMMAND_BULL****", "blargo"); // not a command at all, should result in error
define("SSH_COMMAND_LS", "ls -al"); // a valid command
try {
$ims = MyServer::fetch_by_id($GLOBALS["jdbo"], 20); // fetches an object representing a cloud server
echo "preparing to connect\n";
$connection = ssh2_connect($ims->public_ip, 22);
if ($connection === FALSE) {
throw new Exception("connection failed and returned FALSE.");
}
if (!is_resource($connection)) {
echo "NOT A RESOURCE\n";
var_dump($connection);
throw new Exception("connection is not a resource");
}
echo "connected, preparing to authenticate\n";
// this returns true on success, false on failure
if (!ssh2_auth_password($connection, "root", $ims->admin_password)) {
throw new Exception("Authentication failed");
}
echo "authentication successful, preparing to exec command:\n" . SSH_COMMAND_BULL**** . "\n";
$stream = ssh2_exec($connection, SSH_COMMAND_BULL****);
$error_stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
if ($stream === FALSE) {
throw new Exception("ssh2_exec failed, returning FALSE");
}
echo "command complete, reading main stream\n";
// read up to 1MB from the stream
$output = stream_get_contents($stream, 1000000); // this command blocks when there is an error
echo "stream read\n";
fclose($stream);
echo "stream closed\n";
if ($output === FALSE) {
throw new Exception("Failed to read stream contents");
}
echo "=== OUTPUT ===\n" . $output . "\n======\n";
echo "reading error stream\n";
$error_output = stream_get_contents($error_stream, 1000000);
echo "error stream read\n";
fclose($error_stream);
echo "error_stream_closed\n";
if ($error_output === FALSE) {
throw new Exception("Failed to read error stream contents");
}
echo "=== ERROR OUTPUT ===\n" . $error_output . "\n======\n";
echo "script complete\n";
} catch (Exception $e) {
die("An exception was caught:" . $e->getMessage() . "\n\n");
}
The output:
preparing to connect
connected, preparing to authenticate
authentication successful, preparing to exec command:
blargo
command complete, reading main stream
(script hangs here, refusing to go forward)
Interestingly, if I execute a valid command, the script will complete without any problems. The problem is that I can't seem to find any data value that will tell me if there has been an error or not. the ssh2_exec command does not return FALSE when the command is bad. It still returns a valid resource so there's nothing to indicate there was a problem.