PHP fread ssh stream significantly slow -
scenario: needed function stdout
of command run through ssh asynchronously. has various uses including (and importantly) reading files through ssh. important feature of function is asynchronous, hence can display output returned server (or give estimate of file download progress). differs common approach of using ssh_move()
download files.
function ssh_exec($dsn, $cmd, $return=true, $size_est=null){ $buffer_size = $return ? (1024 * 1024) : 1; debug('ssh2_exec '.$cmd); $stream = ssh2_exec(ssh_open($dsn), $cmd); debug('stream_set_blocking'); stream_set_blocking($stream, true); debug('ssh2_fetch_stream'); $stream_out = ssh2_fetch_stream($stream, ssh2_stream_stdio); stream_set_blocking($stream_out, true); debug('stream_get_contents'); $data = ''; $stime = $oldtime = microtime(true); $data_len = 0; if(!$return){ write_message("\033[0m".' execution output:'.php_eol.' '); } while(!feof($stream_out)){ $buff = fread($stream_out, $buffer_size); if($buff===false)throw new exception('unexpected result fread().'); if($buff===''){ debug('empty result fread()...breaking.'); break; } $data .= $buff; if($return){ $buff_len = strlen($buff); $data_len += $buff_len; $newtime = microtime(true); debugo('stream_get_contents '.bytes_to_human($data_len) .' @ '.bytes_to_human($buff_len / ($newtime - $oldtime)).'/s' .' ['.($size_est ? number_format($data_len / $size_est * 100, 2) : '???').'%]'); $oldtime = $newtime; }else{ echo str_replace(php_eol, php_eol.' ', $buff); } } if($return){ debugo('stream_get_contents transferred '.bytes_to_human(strlen($data)).' in '.number_format(microtime(true) - $stime, 2).'s'); return $data; } }
usage: function used so:
$dsn = 'ssh2.exec://root:pass@host/'; $size = ssh_size($dsn, 'bigfile.zip'); $zip = ssh_exec($dsn, 'cat bigfile.zip', true, $size);
note 1: explanation of non-standard functions:
debug($message)
- writes debug message console.ssh_open($dsn)
- takes in ssh uri , returns ssh connection handle.bytes_to_human($bytes)
- converts number of bytes human readable format (eg: 6gb)debugo($message)
- samedebug()
overwrites last line.
note 2: parameter $size_est
used in progress indicator; you'd first file size , attempt download (as in example). optional can ignored when want run ssh command.
the problem: running same download operation via scp root@host:/bigfile.zip ./
, speeds 1mb/s whereas script seems limit 70kb/s. i'd know why , how improve this.
edit: also, i'd know how/if $buffer_size
difference.
you should able use phpseclib, pure php ssh implementation, this. eg.
$ssh->exec('cat bigfile.zip', false); while (true) { $temp = $this->_get_channel_packet(net_ssh2_channel_exec); if (is_bool($temp)) { break; } echo $temp; }
Comments
Post a Comment