scp y comprimir al mismo tiempo, sin guardado intermedio

64

¿Cuál es la forma canónica de:

  • scp un archivo a una ubicación remota
  • comprimir el archivo en tránsito ( taro no, archivo único o carpeta completa, 7zao algo más aún más eficiente)
  • hacer lo anterior sin guardar archivos intermedios

Estoy familiarizado con tuberías de carcasa como esta:

tar cf - MyBackups | 7za a -si -mx=9 -ms=on MyBackups.tar.7z

esencialmente:

  • rodar una carpeta completa en una sola tar
  • pasar los datos a través stdoutde stdindel programa de compresión
  • aplicar compresión agresiva

¿Cuál es la mejor manera de hacer esto a través de un sshenlace, con el archivo aterrizando en el sistema de archivos remoto?


Prefiero no sshfsmontar.


Esto no funciona:

scp <(tar cvf - MyBackups | 7za a -si -mx=9 -so) localhost:/tmp/tmp.tar.7z

porque:

/dev/fd/63: not a regular file
Robottinosino
fuente

Respuestas:

103

Hay muchas formas de hacer lo que quieres. Lo más simple es usar una pipa:

tar zcvf -  MyBackups | ssh user@server "cat > /path/to/backup/foo.tgz"

Aquí, la compresión está siendo manejada por tarqué llamadas gzip( zflag). También puede usar compress( Z) y bzip( j). Para 7zhacer esto:

tar cf - MyBackups | 7za a -si -mx=9 -ms=on MyBackups.tar.7z | 
   ssh user@server "cat > /path/to/backup/foo.7z"

La mejor manera, sin embargo, es probablemente rsync.

   Rsync is a fast and extraordinarily versatile  file  copying  tool.   It  can  copy
   locally, to/from another host over any remote shell, or to/from a remote rsync dae‐
   mon.  It offers a large number of options that control every aspect of its behavior
   and  permit  very  flexible  specification of the set of files to be copied.  It is
   famous for its delta-transfer algorithm, which reduces the amount of data sent over
   the network by sending only the differences between the source files and the exist‐
   ing files in the destination.  Rsync is widely used for backups and  mirroring  and
   as an improved copy command for everyday use.

rsynctiene forma demasiadas opciones. Realmente vale la pena leerlos, pero a primera vista dan miedo. Sin embargo, los que le interesan en este contexto son:

    -z, --compress              compress file data during the transfer
        --compress-level=NUM    explicitly set compression level

   -z, --compress
          With this option, rsync compresses the file data as it is sent to the desti‐
          nation machine, which reduces the amount of data being transmitted --  
          something that is useful over a slow connection.

          Note  that this option typically achieves better compression ratios than can
          be achieved by using a compressing remote shell or a  compressing  transport
          because  it takes advantage of the implicit information in the matching data
          blocks that are not explicitly sent over the connection.

Entonces, en su caso, querría algo como esto:

rsync -z MyBackups user@server:/path/to/backup/

Los archivos se comprimirían durante el tránsito y llegarían descomprimidos al destino.


Algunas opciones más:

  • scp en sí mismo puede comprimir los datos

     -C      Compression enable.  Passes the -C flag to ssh(1) to
             enable compression.
    
    $ scp -C source user@server:/path/to/backup
    
  • Puede haber una manera de obtener rsyncy 7zajugar bien, pero no tiene sentido hacerlo. La ventaja rsynces que solo copiará los bits que han cambiado entre los archivos locales y remotos. Sin embargo, un pequeño cambio local puede dar como resultado un archivo comprimido muy diferente, por lo que no tiene sentido usarlo rsync. Simplemente complica las cosas sin beneficio. Simplemente use directo sshcomo se muestra arriba. Si realmente quieres hacer esto, puedes intentar dando una subshell como argumento para rsync. En mi sistema, no pude hacer que esto funcione 7zaporque no le permite escribir datos comprimidos en un terminal. Quizás su implementación es diferente. Pruebe algo como ( esto no funciona para mí ):

    rsync $(tar cf - MyBackups | 7za a -an -txz -si -so) \
      user@server:/path/to/backup
    
  • Otro punto es que 7z no debe usarse para copias de seguridad en Linux . Como se indica en la 7zpágina del manual:

    NO UTILICE el formato 7-zip para fines de copia de seguridad en Linux / Unix porque:
    - 7-zip no almacena el propietario / grupo del archivo.

terdon
fuente
3
Una buena nota para agregar es que, a menos que esté transfiriendo a través de una red generalmente lenta, digamos Internet, es mejor evitar la compresión, ya que solo disminuye la velocidad de transferencia. En una LAN, -zes al menos el doble de lento. Para una mayor velocidad de la que rsyncing sobre ssh, configurar un demonio rsync rsync y el uso de -Wla bandera (archivos de copias conjunto (w / o algoritmo delta-xfer).
laebshade
2
¡Gracias! Voy a aceptar esta gran respuesta, pero por favor, agregue una línea de comando completa e independiente que use ambos rsync y 7za , con salida final al sistema de archivos remoto. Me gustó -zpero me gustaría desacoplar la etapa de compresión, así que ... ¿cómo lo usaría rsyncen ese caso, por favor?
Robottinosino
2
@Robottinosino ver respuesta actualizada. No tiene sentido usar rsynccon 7z. Se debe trabajar con rsync y una subshel como se muestra, pero no pude encontrar la manera de todos modos.
terdon
44
+1 para scp -C. No había suficiente espacio en el disco remoto para contener el archivo comprimido, por lo que no pude comprimir antes de la transferencia. Una pequeña opción de línea de comando hizo que mi problema desapareciera.
user37931
1
@knutole simplemente comprime el archivo primero, luego rsync. Haga una nueva pregunta si necesita más detalles.
terdon
13

Creo que este comando hará el truco

ssh user@host "cd /path/to/data/;tar zc directory_name" | tar zx 

EDITAR: una versión anterior tenía dos opciones "f" incorrectas.

Ahora, antes que nada, debe ejecutar este comando desde el host de destino. Y detalles a explicar:

  1. ssh user @ host abrirá la conexión a la máquina host, desde donde se transferirán los datos.
  2. cd / path / to / data llevará al directorio donde se almacenan los datos requeridos
  3. tar zc * iniciará la compresión y la pondrá en STDOUT
  4. Ahora pipe (|) canalizará el STDOUT de la fuente al STDIN del destino donde se está ejecutando "tar zx" y descomprimirá continuamente el flujo de datos proveniente de la fuente.

Como puede ver, este comando comprime sobre la marcha y ahorra ancho de banda. También puede usar otras compresiones para obtener mejores resultados, pero recuerde que la compresión y la descompresión necesitan ciclos de CPU.

Referencia

dkbhadeshiya
fuente
tar: La antigua opción 'f' requiere un argumento.
Dimitri Kopriwa
7

Pequeña mejora para la respuesta de dkbhadeshiya : no tiene que hacerlo cd dir, simplemente especifique el directorio de trabajo en su tarlugar:

ssh user@host "tar -C /path/to/data/ -zc directory_name" | tar zx 

También puede cargar el directorio de la misma manera:

tar zc directory_name/ | ssh user@host "tar zx -C /new/path/to/data/"
tsionyx
fuente