PHP-fread-ssh流速度非常慢
场景:我需要一个函数来获取通过SSH异步运行的命令的PHP-fread-ssh流速度非常慢,php,ssh,file-transfer,download-speed,Php,Ssh,File Transfer,Download Speed,场景:我需要一个函数来获取通过SSH异步运行的命令的STDOUT。这有多种用途,包括(最重要的是)通过SSH读取文件。 此函数的一个重要特性是它是异步的,因此我可以在从服务器返回输出时显示输出(或给出文件下载进度的估计值)。这与使用ssh\u move()下载文件的常见方法不同 function ssh_exec($dsn, $cmd, $return=true, $size_est=null){ $BUFFER_SIZE = $return ? (1024 * 1024) : 1;
STDOUT
。这有多种用途,包括(最重要的是)通过SSH读取文件。
此函数的一个重要特性是它是异步的,因此我可以在从服务器返回输出时显示输出(或给出文件下载进度的估计值)。这与使用ssh\u move()
下载文件的常见方法不同
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 from fread().');
if($buff===''){
debug('Empty result from 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;
}
}
用法:该函数的用法如下:
$dsn = 'ssh2.exec://root:pass@host/';
$size = ssh_size($dsn, 'bigfile.zip');
$zip = ssh_exec($dsn, 'cat bigfile.zip', true, $size);
注1:一些非标准功能的说明:
-将调试消息写入控制台debug($message)
-接收ssh URI并返回ssh连接句柄ssh\u open($dsn)
-将字节数转换为人类可读的格式(例如:6gb)字节到人类($bytes)
-与debugo($message)
相同,但覆盖最后一行debug()
$size\u est
;通常,您会先获取文件大小,然后尝试下载(如我的示例所示)。它是可选的,因此当您只想运行SSH命令时可以忽略它
问题:通过scp运行相同的下载操作root@host:/bigfile.zip./
,我的速度最高可达1mb/s,而此脚本似乎限制为70kb/s。我想知道为什么以及如何改进这一点
编辑:另外,我想知道$BUFFER\u SIZE
有什么不同。您应该能够使用,来完成这项工作。例如
$ssh->exec('cat bigfile.zip', false);
while (true) {
$temp = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC);
if (is_bool($temp)) {
break;
}
echo $temp;
}