2012-05-09 19 views
5

Tengo 2 servidores Linux en la misma LAN.
Uso de PHP que necesito para copiar 100000 pequeños archivos (10KB) desde el servidor A al servidor B.forma rápida de transferir a la red una gran cantidad de archivos pequeños con PHP

Ahora estoy usando ssh2_scp_send y su muy lento (10K archivos en 20 minutos).

¿Cómo hacerlo más rápido?

+2

archivarlos y luego copiar .. – Vytautas

+0

Dijo claramente 'Usando php'. – Manuel

+0

es una solución posible pero más complicada. –

Respuesta

0

¿Se puede ejecutar el proceso externo a través de PHP? Si puede, rsync es la manera más rápida de hacer la copia

0

Otra opción sería postal:

<?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(); 
?> 

Transferencia de que un archivo y descomprimir en el otro extremo, y el uso de zip_entry_open y zip_entry_read en el otro.

También me sugieren en trozos de decir 1000 archivos a la vez?

0

Es probable que la sobrecarga de enviar una gran cantidad de archivos pequeños es la desaceleración aquí.

Se puede archivarlo en el servidor local, shell_exec()

enviarlo al servidor remoto, ssh2_scp_send()

luego expandirlo en el otro extremo. ssh2_exec()

Mi sensación es que la sobrecarga de archivar/expandir será menor, pero no he probado esto.

4

Uso de TAR gzipped través de un túnel SSH es veloz. Magnitudes más rápidas que pura scp, particularmente con respecto a muchos archivos pequeños. Este es un ejemplo de la línea de comandos de Linux :

usuario @ # local cd/fuente /; tar czf - * | ssh usuario @ distancia "cd/target /; tar xzf -"


Actualización: a lo solicitado, aquí se vaya con una solución PHP puro - tenía un buen rato jugando a cabo esta poco complicado.

Nota: Es necesario PHPs libssh extension para que esto funcione. Además, parece que STDIN solo está disponible cuando se utilizan las envolturas de flujo para SSH.

Esto no tiene casi ninguna sobrecarga, ya que está funcionando con corrientes directa y su CPU es más probable siempre más rápido que el enlace de red que se está usando para la transferencia.

Para el comercio de la red frente a velocidad de la CPU, se puede quitar la opción -z desde la línea de comandos. (Menos uso de la CPU, pero más datos sobre el alambre)

ejemplo Código:

<?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; } 
} 
Cuestiones relacionadas