--- /usr/local/cacti/scripts/ss_get_by_ssh.php 2013-03-26 16:48:45.214961265 -0500 +++ ./ss_get_by_ssh.php 2013-03-26 16:48:50.473599498 -0500 @@ -28,6 +28,7 @@ $ssh_port = 22; # SSH port $ssh_iden = '-i /var/www/cacti/.ssh/id_rsa'; # SSH identity $ssh_tout = 10; # SSH connect timeout +$ssh_r_tout = 10; # SSH remote timeout $nc_cmd = 'nc -C -q1'; # How to invoke netcat $cache_dir = '/tmp'; # If set, this uses caching to avoid multiple calls. $poll_time = 300; # Adjust to match your polling interval. @@ -570,7 +571,7 @@ # Execute the command to get the output and return it. # ============================================================================ function get_command_result($cmd, $options) { - global $debug, $ssh_user, $ssh_port, $ssh_iden, $ssh_tout, $use_ssh; + global $debug, $ssh_user, $ssh_port, $ssh_iden, $ssh_tout, $ssh_r_tout, $use_ssh; $use_ssh = isset($options['use-ssh']) ? $options['use-ssh'] : $use_ssh; # If there is a --file, we just use that. @@ -586,13 +587,44 @@ $final_cmd = $use_ssh ? "$ssh '$cmd'" : $cmd; debug($final_cmd); $start = microtime_float(); - $result = `$final_cmd`; # XXX this is the ssh command. + + // Use proc_open and stream_select to handle remote command timeouts. + $descriptorspec = array( + 0 => array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "w"), + ); + + $pipes = array(); + $endtime = time() + $ssh_r_tout; + + $process = proc_open($final_cmd, $descriptorspec, $pipes); + if (is_resource($process)) { + do { + $timeleft = $endtime - time(); + $read = array($pipes[1]); + stream_select($read, $write = NULL, $exeptions = NULL, 1, NULL); + if(!empty($read)) { + $result .= fread($pipes[1], 8192); + } + } while(!feof($pipes[1]) && $timeleft > 0); + + if($timeleft <= 0) { + $result = "timed out"; + proc_terminate($process); + } + } else { + $result = "proc_open failed"; + } + $end = microtime_float(); debug(array("Time taken to exec: ", $end - $start)); debug(array("result of $final_cmd", $result)); return $result; } + + # ============================================================================ # Extracts the numbers from a string. You can't reliably do this by casting to # an int, because numbers that are bigger than PHP's int (varies by platform)