web-dev-qa-db-fra.com

scp et compresser en même temps, pas de sauvegarde intermédiaire

Quelle est la manière canonique de:

  • scp un fichier vers un emplacement distant
  • compresser le fichier en transit (tar ou non, fichier unique ou dossier entier, 7za ou autre chose encore plus efficace)
  • faire ce qui précède sans enregistrer les fichiers intermédiaires

Je connais les tuyaux Shell comme celui-ci:

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

essentiellement:

  • rouler un dossier entier dans un seul tar
  • passer les données par stdout à stdin du programme de compression
  • appliquer agressif compression

Quelle est la meilleure façon de le faire sur un lien ssh, avec le fichier atterrissant sur le système de fichiers distant?


Je préfère ne pas monter sshfs.


Cela ne fonctionne pas:

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

parce que:

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

Il existe de nombreuses façons de faire ce que vous voulez. Le plus simple est d'utiliser un pìpe:

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

Ici, la compression est gérée par tar qui appelle gzip (indicateur z). Vous pouvez également utiliser compress (Z) et bzip (j). Pour 7z, procédez comme suit:

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

Cependant, la meilleure façon est probablement 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.

rsync a trop trop d'options. Cela vaut vraiment la peine de les lire, mais ils font peur à première vue. Ceux qui vous intéressent dans ce contexte sont les suivants:

    -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.

Donc, dans votre cas, vous voudriez quelque chose comme ça:

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

Les fichiers seraient compressés pendant le transit et arriveraient décompressés à destination.


Quelques choix supplémentaires:

  • scp lui-même peut compresser les données

     -C      Compression enable.  Passes the -C flag to ssh(1) to
             enable compression.
    
    $ scp -C source user@server:/path/to/backup
    
  • Il existe peut-être un moyen d'obtenir rsync et 7za pour jouer à Nice mais cela ne sert à rien. L'avantage de rsync est qu'il ne copiera que les bits qui ont changé entre les fichiers local et distant. Cependant, une petite modification locale peut entraîner un fichier compressé très différent, il est donc inutile d'utiliser rsync pour cela. Cela complique simplement les choses sans aucun avantage. Utilisez simplement ssh comme indiqué ci-dessus. Si vous voulez vraiment faire cela, vous pouvez essayer en donnant un sous-shell comme argument à rsync. Sur mon système, je n'ai pas pu faire fonctionner cela avec 7za car il ne vous permet pas d'écrire des données compressées sur un terminal. Peut-être que votre implémentation est différente. Essayez quelque chose comme (cela ne fonctionne pas pour moi):

    rsync $(tar cf - MyBackups | 7za a -an -txz -si -so) \
      user@server:/path/to/backup
    
  • Un autre point est que 7zne doit pas être utilisé pour les sauvegardes sous Linux. Comme indiqué sur le 7z page de manuel:

    N'UTILISEZ PAS le format 7-Zip à des fins de sauvegarde sous Linux/Unix car:
    - 7-Zip ne stocke pas le propriétaire/groupe du fichier.

111
terdon

Je pense que cette commande fera l'affaire

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

EDIT: une version antérieure était avec deux mauvaises options "f".

Maintenant, vous devez d'abord exécuter cette commande à partir de l'hôte cible. Et les détails à expliquer:

  1. ssh user @ Host ouvrira la connexion à la machine Host, d'où les données doivent être transférées.
  2. cd/path/to/data ira dans le répertoire où les données requises sont stockées
  3. tar zc * lancera la compression et la placera dans STDOUT
  4. Maintenant, pipe (|) canalisera le STDOUT de la source vers le STDIN de la destination où "tar zx" s'exécute et décompressera en continu le flux de données provenant de la source.

Comme vous pouvez le voir, cette commande compresse à la volée et économise la bande passante. Vous pouvez également utiliser d'autres compressions pour de meilleurs résultats, mais n'oubliez pas que la compression et la décompression nécessitent des cycles CPU.

Référence

15
dkbhadeshiya

Petite amélioration pour le réponse de dkbhadeshiya : vous n'avez pas à faire cd dir, spécifiez simplement le répertoire de travail dans le tar à la place:

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

Vous pouvez également télécharger le répertoire de la même manière:

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