¿Cómo puedo copiar mejor grandes cantidades de archivos pequeños sobre scp?


59

Tengo un directorio que tiene varios gigabytes y varios miles de archivos pequeños. Quiero copiarlo a través de la red con scp más de una vez. El tiempo de CPU en las máquinas de origen y destino es económico, pero la sobrecarga de la red agregada al copiar cada archivo individualmente es enorme. Lo alquilaría con tar / gzip y lo enviaría, pero la máquina fuente tiene poco disco.

¿Hay alguna manera de canalizar la salida de tar -czf <output> <directory>scp? Si no, ¿hay otra solución fácil? Mi máquina fuente es antigua (SunOS), así que prefiero no instalar nada en ella.

Respuestas:


104

Puede canalizar alquitrán a través de una sesión ssh:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"

3
+1 solución de tubería de alquitrán. Si tiene más ancho de banda y menos CPU, puede eliminar el indicador de compresión (aunque gzip es bastante ligero).
dietbuddha

2
Y podría soltar el indicador de compresión y, en su lugar, activarlo en SSH ( ssh -Co Compression yesen ~/.ssh/config).
sam hocevar

3
Nunca pensé en usar alquitrán como este. Bueno, por eso vengo aquí!
Sr. Shickadance

2
Este comando podría hacerse un poco más corto:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
carlito

2
@Greg el tablero es una convención en software compatible con POSIX que significa STDIN o STDOUT según el contexto. El primer guión significa 'leer desde / dev / stdin' y el segundo, que en realidad se ejecuta en el host remoto, significa '/ dev / stdin'. La tubería y el ssh conectan estos dos procesos. Ver unix.stackexchange.com/questions/16357/... para aprender más.
Richard Metzler

22

El alquitrán con compresión bzip2 debería quitar tanta carga de la red y de la CPU.

$ tar -C /path/to/src/dir -jcf - ./ | ssh user@server 'tar -C /path/to/dest/dir -jxf -'

No se usa -vporque la salida de pantalla puede ralentizar el proceso. Pero si desea una salida detallada, úsela en el lado local de tar ( -jcvf), no en la parte remota.

Si copia repetidamente sobre la misma ruta de destino, como actualizar una copia de seguridad, su mejor opción es rsync con compresión.

$ rsync -az -e ssh /path/to/src/dir/ user@server:/path/to/dest/dir/

Observe que las rutas src y dest terminan con a /. Una vez más, no use -vy -Pmarcas a propósito, agréguelos si necesita resultados detallados.


16

uso rsync, usa SSH.

Uso:

rsync -aPz /source/path destination.server:remote/path

Los conmutadores rsync se preocupan por la compresión y la información del Nodo I. -PMuestra el progreso de cada archivo.

Puede usar scp -C, lo que permite la compresión, pero si es posible, use rsync.


Desafortunadamente, rsync no está disponible en la máquina fuente, y tampoco lo está sshd.
nmichaels

1
sshd no es necesario para esas operaciones en la máquina del cliente.
polemon

3

Puede ejecutar taren ambos extremos usando ssh. scpes parte de la sshfamilia de la bondad, por lo que probablemente la tengas en ambos extremos.

 8:03AM 12 % tar cf - some_directory | ssh dest_host "tar xf -"

También puede haber una manera de trabajar gzip o bzip2 en la tubería para disminuir el tráfico de la red.


3

La respuesta de @ pdo es buena, pero se puede aumentar la velocidad con un búfer y una buena compresión y agregar una barra de progreso.

A menudo, la red es el cuello de botella y la velocidad varía con el tiempo. Por lo tanto, ayuda a almacenar en búfer los datos antes de enviarlos a través de la red. Esto se puede hacer con pv.

Además, generalmente se puede aumentar la velocidad con un algoritmo de compresión adecuado. Gzip (como se usó anteriormente) es un algoritmo de compresión rápida, pero en general zstandard ( zstd) (y para relaciones de compresión altas LZMA / LZMA2 ( xz) se comprimirá mejor y será más rápido al mismo tiempo. Los nuevos xz y zstd ya tienen soporte de núcleo múltiple incorporado Para usar gzip con múltiples núcleos se puede usar pigz.

Aquí hay un ejemplo para enviar datos con una barra de progreso, almacenamiento en búfer y compresión estándar z en una red:

tar cf - . | pv -perabs $(du -sk . | cut -f 1)K | zstd -14 --long=31 -T0 | pv -qCB 512M | ssh user@host "cd /wherever && pv -qCB 512M | zstd -cd -T0 --long=31 | tar xf -"

El primero pves mostrar el progreso ( p ), el tiempo estimado ( e ), la tasa de transferencia ( r ), la tasa promedio ( a ), el total de bytes transferidos ( b ). El tamaño total es estimada con duy se añade a la opción (tamaño s ). El progreso se mide antes de la compresión y el almacenamiento en búfer, por lo tanto, no es muy preciso, pero sigue siendo útil.

zstdse usa con la configuración de compresión 14 . Este número se puede reducir o aumentar según la red y la velocidad de la CPU, por lo que zstd es un poco más rápido que la velocidad de la red. Con cuatro núcleos en un Haswell 3.2 GHz, la CPU 14 proporciona una velocidad de alrededor de 120 MB / s. En el ejemplo, se utiliza el modo largo 31 (utiliza una ventana de 2 GB, necesita mucha RAM, pero es muy bueno, por ejemplo, para comprimir los volcados de la base de datos). Las opciones T0 establecen la cantidad de hilos en el número de núcleos. Se debe tener en cuenta que, junto con el modo largo, estas configuraciones utilizan mucha memoria.

Un problema con zstd es que la mayoría de los sistemas operativos no incluyen la versión> = 1.3.4. Esta versión es necesaria para un soporte multi core y largo adecuado. Si no está disponible, se puede compilar e instalar desde https://github.com/facebook/zstd con solo make -j4 && sudo make install. En lugar de zstd, también se puede usar xz o pigz. xz es lento pero se comprime muy bien (bueno sobre conexiones lentas), pigz / gzip es rápido pero no se comprime tan bien. pvluego se usa nuevamente, pero para el almacenamiento en búfer ( qpara silencio, Cpara el modo sin empalme [siempre necesario para el almacenamiento en búfer] y Bpara establecer el tamaño del búfer).

En el ejemplo, también se usa un búfer en el lado del receptor. Esto a menudo es innecesario (porque la velocidad de escritura de la descompresión y el disco duro es más alta que la velocidad de la red), pero generalmente tampoco daña.


2

Si tiene gzip en ambos extremos: sourcehost$ cd sourcedir && tar cf - . | gzip -c - | ssh user@destinationhost "cd destinationdir && gzip -c -d | tar xf -"

Si no tiene gzip en la máquina de origen, asegúrese de tener descomprimido en el destino: sourcehost$ cd sourcedir && tar cf - . | compress | ssh user@destinationhost "cd destdir && uncompress | tar xf -"

Esto sería más rápido que primero comprimirlo, luego enviarlo y luego descomprimirlo, y no requiere espacio en disco adicional en ninguno de los lados. Coloqué la bandera de compresión (z) en el alquitrán, porque probablemente no la tengas en el lado antiguo.


2

O puede hacerlo al revés si es necesario. Eso es tirar del tarball sobre la red en lugar de empujarlo como se ha sugerido. Esto no resuelve la parte repetitiva de su pregunta y rsync es mejor para eso, pero probablemente haya interruptores tar para ayudarlo.

Entonces en la máquina local:

ssh remote 'tar zcf - /etc/resolv.conf' | tar zxf -

Lo mejor es estar en el directorio correcto primero o debe usar el interruptor -C en el comando untaring al final.

Solo menciono esto en caso de que sea necesario. Es para mí, ya que en mi situación mi servidor local está detrás de nat, por lo que tomaría un tiempo en la red para poder hacerlo de la manera que se mencionó anteriormente.

HTH


1

O monte el sistema de archivos remoto a través de sshfs

sshfs user@remotehost:/path/on/remote /path/on/local

1

Si bien no es el más elegante, especialmente porque no está copiando un solo archivo zip o tar y doblemente, ya que no ayuda a reducir la sobrecarga de la red, mi única opción fue usar scp -r:

-r

      Copie recursivamente directorios completos. Tenga en cuenta que scp sigue los enlaces simbólicos encontrados en el recorrido del árbol.
Fuente: scp (1)

Me encontraba con problemas al quedarme sin espacio en disco con un archivo tar comprimido de 30 GB. Pensé que gunzip podría hacerlo en línea, es decir, eliminar el original cuando se estaba descomprimiendo (y es posible que haya perdido un resultado de Google) pero no pude encontrar nada.

Finalmente, debido a que estaba cansado de intentar varias veces esperar a que un nuevo archivo TAR o ZIP se termine de taradear o comprimir, finalmente lo hice:

  1. Desde el servidor / PC / laptop original, navegue hasta el directorio donde se encuentra su carpeta con numerosos archivos / carpetas.
  2. scp -r source_folder_name yourname@yourservername:destination_folder_name

Luego solo toma un poco de cerveza, café o palomitas de maíz y espera. Lo bueno es que scp volverá a intentarlo si la conexión de red "se detiene". Solo espero que no se caiga por completo.


OK, esto claramente toma menos tiempo que escribir mil scpcomandos. Pero la pregunta se refiere a "sobrecarga de red". ¿Su solución utiliza la red menos que copiar cada archivo individualmente? ¿Es su solución superior de alguna manera a las siete que ya se han publicado?
G-Man dice 'reinstalar a Monica'

Snap, mi mal, perdí totalmente la parte superior de la red, gracias por señalar eso @ G-Man. Actualicé la respuesta, sigo sintiendo que podría ser útil si alguien se topa con un problema similar al que yo tuve y cuando me topé con esta pregunta.
JGlass
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.