我在同一个局域网上有2台Linux服务器 使用PHP我需要将100000个小(10KB)文件从服务器A复制到服务器B.
现在我正在使用ssh2_scp_send,它非常慢(20分钟内有10K文件)。
如何加快速度?
答案 0 :(得分:4)
通过SSH隧道使用gzipped TAR非常快。幅度比纯scp
快,特别是对于许多小文件。以下是 linux命令行的示例:
user @ local#cd / source /; tar czf - * | ssh user @ remote“cd / target /; tar xzf - ”
更新:根据要求,您可以使用纯PHP解决方案 - 有一些乐趣可以摆脱这个棘手的问题。
注意:您需要PHPs libssh extension才能生效。此外,STDIN似乎仅在使用SSH的流包装器时可用。
这几乎没有开销,因为它直接在流上运行,并且您的CPU很可能总是比您用于传输的网络链接更快。
要交换网络与CPU速度,可以从命令行中删除选项-z
。 (CPU使用率越低,但线路上的数据越多)
代码示例:
<?php
$local_cmd = "cd /tmp/source && tar -czf - *";
$remote_cmd = "tar -C /tmp/target -xzf -";
$ssh = new SSH_Connection('localhost');
$auth = $ssh->auth_password('gast', 'gast');
$bytes = $ssh->command_pipe($local_cmd, $remote_cmd);
echo "finished: $bytes bytes of data transfered\n";
class SSH_Connection {
private $link;
private $auth;
function __construct ($host, $port=22) {
$this->link = @ssh2_connect('localhost', 22);
}
function auth_password ($username, $password) {
if (!is_resource($this->link))
return false;
$this->auth = @ssh2_auth_password($this->link, $username, $password);
return $this->auth;
}
function command_pipe ($localcmd, $remotecmd) {
if (!is_resource($this->link) || !$this->auth)
return false;
// open remote command stream (STDIN)
$remote_stream = fopen("ssh2.exec://{$this->link}/$remotecmd", 'rw');
if (!is_resource($remote_stream))
return false;
// open local command stream (STDOUT)
$local_stream = popen($localcmd, 'r');
if (!is_resource($local_stream))
return false;
// connect both, pipe data from local to remote
$bytes = 0;
while (!feof($local_stream))
$bytes += fwrite($remote_stream,fread($local_stream,8192));
// close streams
fclose($local_stream);
fclose($remote_stream);
return $bytes;
}
function is_connected () { return is_resource($this->link); }
function is_authenticated () { return $this->auth; }
}
答案 1 :(得分:0)
您可以通过PHP执行外部流程吗?如果可以,rsync是更快的复制方式
答案 2 :(得分:0)
另一种选择是Zip:
<?php
$zip = new ZipArchive();
if ($zip->open('TempFileToTransfer.zip', ZIPARCHIVE::CREATE)!==TRUE) {
exit("cannot open <$filename>\n");
}
$zip->addFile('File 1');
$zip->addFile('File 2');
$zip->addFile('File 3');
$zip->close();
?>
传输一个文件并在另一端解压缩,并在另一端使用zip_entry_open和zip_entry_read。
我还建议一次说出1000个文件?
答案 3 :(得分:0)
发送大量小文件的开销很可能是这里的减速。
您可以将其存档在本地服务器上, 了shell_exec()
将其发送到远程服务器, ssh2_scp_send()
然后在另一端展开它。 ssh2_exec()
我的感觉是,拱形/扩展的开销会减少,但我还没有对此进行测试。