【问题标题】:PHP fread ssh stream significantly slowPHP fread ssh 流明显慢
【发布时间】:2013-04-26 18:20:02
【问题描述】:

场景:我需要一个函数来获取通过 SSH 异步运行的命令的STDOUT。这有多种用途,包括(最重要的是)通过 SSH 读取文件。 这个函数的一个重要特点是它是异步的,因此我可以显示从服务器返回的输出(或估计文件下载进度)。这与使用ssh_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_open($dsn) - 接受一个 SSH URI 并返回一个 SSH 连接句柄。
  • bytes_to_human($bytes) - 将字节数转换为人类可读的格式(例如:6gb)
  • debugo($message) - 与 debug() 相同,但会覆盖最后一行。

注意2:参数$size_est用于进度指示器;通常你会先获取文件大小,然后尝试下载它(如我的示例所示)。它是可选的,因此当您只想运行 SSH 命令时可以忽略它。

问题: 通过scp root@host:/bigfile.zip ./ 运行相同的下载操作,我的速度高达 1mb/s,而这个脚本似乎限制为 70kb/s。我想知道为什么以及如何改进它。

编辑:另外,我想知道$BUFFER_SIZE 有什么不同/如果有什么不同。

【问题讨论】:

    标签: php ssh file-transfer download-speed


    【解决方案1】:

    您应该可以使用 phpseclib, a pure PHP SSH implementation 来执行此操作。例如。

    $ssh->exec('cat bigfile.zip', false);
    
    while (true) {
        $temp = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC);
        if (is_bool($temp)) {
            break;
        }
        echo $temp;
    }
    

    Might actually be faster too.

    【讨论】:

      猜你喜欢
      • 2012-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 1970-01-01
      • 2012-08-25
      相关资源
      最近更新 更多