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

64

Quel est le moyen canonique de:

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

Je suis familier avec les pipes comme ceci:

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

essentiellement:

  • rouler un dossier entier en un seul tar
  • transmettre des données stdoutau stdinprogramme de compression
  • appliquer une compression agressive

Quelle est la meilleure façon de faire cela sur un sshlien, avec le fichier arrivant sur le système de fichiers distant?


Je préfère ne pas sshfsmonter.


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
Robottinosino
la source

Réponses:

103

Il y a plusieurs façons de faire ce que vous voulez. Le plus simple consiste à utiliser un pìpe:

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

Ici, la compression est gérée par tarquels appels gzip( zdrapeau). Vous pouvez également utiliser compress( Z) et bzip( j). Pour cela 7z, faites ceci:

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

La meilleure façon, cependant, 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.

rsynca beaucoup trop d'options. Cela vaut vraiment la peine de les lire, mais ils sont effrayants à 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 ceci:

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

Les fichiers seraient compressés en transit et arriveraient décompressés à la destination.


Quelques autres choix:

  • 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 y a peut-être un moyen d'obtenir rsyncet 7zade jouer bien, mais cela ne sert à rien. L'avantage rsyncest qu'il ne copiera que les bits qui ont changé entre les fichiers local et distant. Cependant, un petit changement local peut générer un fichier compressé très différent, il est donc inutile de l'utiliser rsync. Cela ne fait que compliquer les choses sans aucun avantage. Il suffit d'utiliser direct sshcomme indiqué ci-dessus. Si vous voulez vraiment faire cela, vous pouvez essayer de donner un argument à un sous-shell rsync. Sur mon système, cela ne fonctionnait pas, 7zacar cela ne vous permettait pas d'écrire des données compressées sur un terminal. Peut-être que votre implémentation est différente. Essayez quelque chose comme ( ça ne marche pas pour moi ):

    rsync $(tar cf - MyBackups | 7za a -an -txz -si -so) \
      user@server:/path/to/backup
    
  • Un autre point est qu'il 7z ne faut pas utiliser pour les sauvegardes sous Linux . Comme indiqué sur la 7zpage 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.

terdon
la source
3
Une bonne remarque à ajouter est que, sauf si vous effectuez un transfert sur un réseau généralement lent, par exemple sur Internet, il est préférable d'éviter la compression, car cela ralentit simplement le taux de transfert. Sur un réseau local, -zc'est au moins deux fois plus lent. Pour encore plus de rapidité que la synchronisation sur SSH, configurez un démon rsync et rsync à l'aide de l'option -Wflag (copie les fichiers en entier (algorithme sans delta-xfer).
laebshade
2
Merci! Je vais accepter cette excellente réponse, mais veuillez ajouter une ligne de commande complète et autonome qui utilise les deux rsync et 7za , avec une sortie finale vers le système de fichiers distant. J'ai aimé -zmais je voudrais découpler la phase de compression alors .. comment pourrais-je utiliser rsyncdans ce cas, s'il vous plaît?
Robottinosino
2
@Robottinosino voir la réponse mise à jour. Il ne sert à rien d'utiliser rsyncavec 7z. Cela devrait fonctionner avec rsync et un sous-serveur comme indiqué, mais je ne pouvais pas trouver comment.
terdon
4
+1 pour scp -C. Il n'y avait pas assez de place sur le disque distant pour contenir le fichier compressé, je ne pouvais donc pas compresser avant le transfert. Une petite option de ligne de commande a résolu mon problème.
user37931
1
@knutole commence simplement par compresser le fichier, puis rsync. Veuillez poser une nouvelle question si vous avez besoin de plus de détails.
terdon
13

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 comportait deux mauvaises options "f".

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

  1. ssh user @ host ouvrira la connexion à la machine hôte à partir de laquelle les données doivent être transférées.
  2. cd / path / to / data mènera au répertoire où les données requises sont stockées
  3. tar zc * lancera la compression et la mettra dans le STDOUT
  4. Maintenant pipe (|) canalisera le STDOUT de la source vers le STDIN de la destination où "tar zx" est en cours d'exécution et le flux de données de décompression en continu provenant de la source.

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

Référence

dkbhadeshiya
la source
tar: L'ancienne option 'f' nécessite un argument.
Dimitri Kopriwa
7

Petite amélioration pour la réponse de dkbhadeshiya : vous n'avez pas à le faire cd dir, il suffit de spécifier le répertoire de travail à la tarplace:

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/"
tsionyx
la source