Comment puis-je copier au mieux un grand nombre de petits fichiers sur scp?

59

J'ai un répertoire qui a plusieurs gigaoctets et plusieurs milliers de petits fichiers. Je veux le copier sur le réseau avec scp plus d'une fois. Le temps de calcul sur les machines source et cible est économique, mais la surcharge réseau ajoutée en copiant chaque fichier individuellement est énorme. Je le tar / gzip et l'envoyer, mais la machine source manque de disque.

Y at-il un moyen pour moi de diriger la sortie de tar -czf <output> <directory>scp? Si non, existe-t-il une autre solution facile? Ma machine source étant ancienne (SunOS), je préfère ne pas installer d’installation dessus.

nmichaels
la source

Réponses:

104

Vous pouvez diriger tar à travers une session ssh:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"
pdo
la source
3
+1 solution de goudron. Si vous avez plus de bande passante et moins de CPU, vous pouvez supprimer l'indicateur de compression (bien que gzip soit assez léger).
dietbuddha
2
Et vous pouvez supprimer l'indicateur de compression et l'activer au lieu de SSH ( ssh -Cou Compression yesin ~/.ssh/config).
Sam Hocevar
3
Jamais pensé à utiliser du goudron comme ça. Eh bien, c'est pourquoi je viens ici!
M. Shickadance
2
Cette commande pourrait être légèrement plus courte:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
carlito
2
@Greg the dash est une convention dans les logiciels compatibles POSIX qui signifie STDIN ou STDOUT en fonction du contexte. Le premier tiret signifie "lire à partir de / dev / stdin" et le second - qui est en réalité exécuté sur l'hôte distant - signifie "/ dev / stdin". Le tuyau et le SSH relient ces deux processus. Voir unix.stackexchange.com/questions/16357/… pour en savoir plus.
Richard Metzler
22

Tar avec la compression bzip2 devrait prendre autant de charge du réseau et du processeur.

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

Ne pas utiliser -vcar la sortie de l'écran peut ralentir le processus. Mais si vous voulez une sortie commentée, utilisez-la du côté local de tar ( -jcvf), pas du côté distant.

Si vous copiez de manière répétée sur le même chemin de destination, comme lors de la mise à jour d'une copie de sauvegarde, votre meilleur choix est rsync avec compression.

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

Notez que les deux chemins src et dest se terminent par un /. Encore une fois, en n'utilisant pas -vet des -Pdrapeaux exprès, ajoutez-les si vous avez besoin d'une sortie détaillée.

forcefsck
la source
16

utiliser rsync, il utilise SSH.

Usage:

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

Les commutateurs rsync se soucient de la compression et des informations I-Node. -Paffiche la progression de chaque fichier.

Vous pouvez utiliser scp -C, ce qui permet la compression, mais si possible, utilisez rsync.

polemon
la source
Malheureusement, rsync n'est pas disponible sur la machine source, pas plus que sshd.
nmichaels
1
sshd n'est pas nécessaire pour ces opérations sur la machine cliente.
polemon
3

Vous pouvez exécuter des tardeux côtés en utilisant ssh. scpfait partie de la sshfamille de la bonté, vous l'avez donc probablement des deux côtés.

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

Il peut y avoir un moyen d’intégrer gzip ou bzip2 dans le pipeline pour réduire également le trafic réseau.

Bruce Ediger
la source
3

La réponse de @ pdo est bonne, mais on peut augmenter la vitesse avec un tampon et une bonne compression et ajouter une barre de progression.

Le réseau est souvent le goulot d’étranglement et la vitesse varie avec le temps. Par conséquent, il est utile de mettre les données en mémoire tampon avant de les envoyer sur le réseau. Cela peut être fait avec avec pv.

De plus, on peut généralement augmenter la vitesse avec un algorithme de compression approprié. Gzip (comme utilisé ci-dessus) est un algorithme de compression rapide, mais en général zstandard ( zstd) (et pour des taux de compression élevés, LZMA / LZMA2 ( xz) se compressera mieux et sera plus rapide en même temps. Les nouveaux xz et zstd ont déjà un support multi-core intégré Pour utiliser gzip avec plusieurs noyaux, vous pouvez utiliser pigz.

Voici un exemple pour envoyer des données avec une barre de progression, une mise en mémoire tampon et une compression zstandard sur un réseau:

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

La première pvconsiste à afficher la progression ( p ), la durée estimée ( e ), le taux de transfert ( r ), le débit moyen ( a ), le nombre total d'octets transférés ( b ). La taille totale est estimée avec duet ajouté à l'option de taille ( s ). La progression est mesurée avant la compression et la mise en mémoire tampon. Par conséquent, elle n’est pas très précise mais reste utile.

zstdest utilisé avec le réglage de compression 14 . Ce nombre peut être réduit ou augmenté en fonction du réseau et de la vitesse du processeur, ainsi zstd est un peu plus rapide que la vitesse du réseau. Avec quatre cœurs sur un processeur Haswell à 3,2 GHz 14, la vitesse est d’environ 120 Mo / s. Dans l'exemple, le mode long 31 (utilise une fenêtre de 2 Go, nécessite beaucoup de mémoire vive, mais est très utile, par exemple, pour compresser les vidages de base de données). Les options T0 définissent le nombre de threads sur le nombre de cœurs. Il faut savoir que, avec le mode long, ces paramètres utilisent beaucoup de mémoire.

Un problème avec zstd est que la plupart des systèmes d'exploitation ne sont pas livrés avec la version> = 1.3.4. Cette version est nécessaire pour un support multi-core et long correct. S'il n'est pas disponible, il peut être compilé et installé à partir de https://github.com/facebook/zstd avec just make -j4 && sudo make install. Au lieu de zstd, on peut aussi utiliser xz ou pigz. xz est lent mais compresse très bien (bon pour les connexions lentes), pigz / gzip est rapide mais compresse moins bien. pvest ensuite utilisé à nouveau, mais pour la mise en mémoire tampon ( qpour le mode silencieux, Cpour le mode sans raccordement (toujours nécessaire pour la mise en mémoire tampon) et Bpour définir la taille de la mémoire tampon).

Dans l'exemple, un tampon est également utilisé du côté du récepteur. Cela est souvent inutile (car la vitesse de décompression et d’écriture sur le disque dur est généralement supérieure à la vitesse du réseau), mais ne nuit généralement pas non plus.

Fabian Heller
la source
2

Si vous avez gzip aux deux extrémités: sourcehost$ cd sourcedir && tar cf - . | gzip -c - | ssh user@destinationhost "cd destinationdir && gzip -c -d | tar xf -"

Si vous n'avez pas gzip sur la machine source, assurez-vous de décompresser la destination: sourcehost$ cd sourcedir && tar cf - . | compress | ssh user@destinationhost "cd destdir && uncompress | tar xf -"

Cela serait plus rapide que de le compresser, puis d'envoyer, puis de décompresser, et cela ne nécessite aucun espace disque supplémentaire de chaque côté. J'ai placé le drapeau de compression (z) sur tar, parce que vous ne l'avez probablement pas du côté ancien.

MattBianco
la source
2

Ou vous pouvez le faire dans l'autre sens si vous en avez besoin. C’est-à-dire tirer la balle sur le réseau plutôt que de la pousser comme cela a été suggéré. Cela ne résout pas la partie répétée de votre question et rsync est préférable pour cela, mais il existe probablement des commutateurs tar pour vous aider.

Donc sur la machine locale:

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

Il est préférable d’être d’abord dans le bon répertoire ou vous devez utiliser le commutateur -C sur la commande untaring à la fin.

Il suffit de mentionner ceci au cas où cela serait nécessaire. C’est pour moi que, comme dans mon cas, mon serveur local est derrière nat, il faudrait donc que le réseau soit sur le point de pouvoir le faire comme il a été mentionné précédemment.

HTH

DaveQB
la source
1

Ou montez le système de fichiers distant via sshfs

sshfs user@remotehost:/path/on/remote /path/on/local
Ivanivan
la source
1

Bien que ce ne soit pas le plus élégant, surtout qu’il ne copie pas un fichier zip ou tar, et qu’il n’aide pas à réduire le nombre de têtes de réseau, mon seul choix était d’utiliser scp -r:

-r

      Copier récursivement des répertoires entiers. Notez que scp suit les liens symboliques rencontrés dans la traversée de l’arbre.
Source: scp (1)

Je rencontrais des problèmes avec un espace disque insuffisant avec un fichier tar compressé de 30 Go. Je pensais que gunzip pourrait le faire en ligne, c'est-à-dire supprimer l'original au moment de le décompresser (et j'ai peut-être manqué un résultat de Google), mais je n'ai rien trouvé.

Enfin, parce que j'étais fatigué d'essayer plusieurs fois d'attendre qu'un nouveau fichier TAR ou ZIP soit fini de tarer ou de compresser, j'ai fini par le faire:

  1. Depuis le serveur / PC / ordinateur portable d'origine, accédez au répertoire où se trouve votre dossier contenant de nombreux fichiers / dossiers.
  2. scp -r source_folder_name yourname@yourservername:destination_folder_name

Ensuite, prenez une bière, un café ou du maïs soufflé et attendez. Le bon point est que scp réessayera si la connexion réseau "se bloque". J'espère juste que ça ne va pas complètement.

JGlass
la source
OK, cela prend clairement moins de temps que de taper mille scpcommandes. Mais la question concerne «la surcharge du réseau». Votre solution utilise-t-elle moins le réseau que la copie individuelle de chaque fichier? Votre solution est-elle supérieure aux sept solutions déjà publiées?
G-Man dit 'Réintégrez Monica' le
Snap, mon mauvais - j'ai totalement manqué la partie des frais généraux de réseau - merci de l'avoir souligné @ G-Man. J'ai mis à jour la réponse, je pense toujours qu'il pourrait être utile que quelqu'un tombe sur un problème similaire à celui que j'avais et qui est tombé sur cette question.
JGlass