web-dev-qa-db-fra.com

Pourquoi le scp est-il si lent et comment le rendre plus rapide?

J'essaie de copier un lot de fichiers avec scp mais c'est très lent. Voici un exemple avec 10 fichiers:

$ time scp cap_* user@Host:~/dir
cap_20151023T113018_704979707.png    100%  413KB 413.2KB/s   00:00    
cap_20151023T113019_999990226.png    100%  413KB 412.6KB/s   00:00    
cap_20151023T113020_649251955.png    100%  417KB 416.8KB/s   00:00    
cap_20151023T113021_284028464.png    100%  417KB 416.8KB/s   00:00    
cap_20151023T113021_927950468.png    100%  413KB 413.0KB/s   00:00    
cap_20151023T113022_567641507.png    100%  413KB 413.1KB/s   00:00    
cap_20151023T113023_203534753.png    100%  414KB 413.5KB/s   00:00    
cap_20151023T113023_855350640.png    100%  412KB 411.7KB/s   00:00    
cap_20151023T113024_496387641.png    100%  412KB 412.3KB/s   00:00    
cap_20151023T113025_138012848.png    100%  414KB 413.8KB/s   00:00    
cap_20151023T113025_778042791.png    100%  413KB 413.4KB/s   00:00    

real    0m43.932s
user    0m0.074s
sys 0m0.030s

Ce qui est étrange, c'est que le taux de transfert est d'environ 413 Ko/s et la taille du fichier est d'environ 413 Ko, donc il devrait vraiment transférer un fichier par seconde, mais cela prend environ 4,3 secondes par fichier.

Avez-vous une idée de l'origine de ces frais généraux et existe-t-il un moyen de le rendre plus rapide?

65
laurent

Le commentaire de @ wurtel est probablement correct: il y a beaucoup de frais généraux pour établir chaque connexion. Si vous pouvez résoudre ce problème vous obtiendrez des transferts plus rapides (et si vous ne pouvez pas, utilisez simplement la solution de contournement rsync de @ roaima). J'ai fait une expérience de transfert de fichiers de taille similaire (head -c 417K /dev/urandom > foo.1 et a fait quelques copies de ce fichier) vers un hôte qui met un certain temps à se connecter (Host4) et un autre qui répond très rapidement (Host1):

$ time ssh $Host1 echo


real    0m0.146s
user    0m0.016s
sys     0m0.008s
$ time scp * $Host1:
foo.1                                         100%  417KB 417.0KB/s   00:00    
foo.2                                         100%  417KB 417.0KB/s   00:00    
foo.3                                         100%  417KB 417.0KB/s   00:00    
foo.4                                         100%  417KB 417.0KB/s   00:00    
foo.5                                         100%  417KB 417.0KB/s   00:00    

real    0m0.337s
user    0m0.032s
sys     0m0.016s
$ time ssh $Host4 echo


real    0m1.369s
user    0m0.020s
sys     0m0.016s
$ time scp * $Host4:
foo.1                                         100%  417KB 417.0KB/s   00:00    
foo.2                                         100%  417KB 417.0KB/s   00:00    
foo.3                                         100%  417KB 417.0KB/s   00:00    
foo.4                                         100%  417KB 417.0KB/s   00:00    
foo.5                                         100%  417KB 417.0KB/s   00:00    

real    0m6.489s
user    0m0.052s
sys     0m0.020s
$ 
17
user4443

Vous pouvez utiliser rsync (sur ssh), qui utilise une seule connexion pour transférer tous les fichiers source.

rsync -avP cap_* user@Host:dir

Si vous n'avez pas rsync (et pourquoi pas !?) vous pouvez utiliser tar avec ssh comme ceci, ce qui évite de créer un fichier temporaire:

tar czf - cap_* | ssh user@Host tar xvzfC - dir

Le rsync est à privilégier, toutes choses égales par ailleurs, car il peut être redémarré en cas d'interruption.

63
roaima

C'est la négociation du transfert qui prend du temps. En général, les opérations sur n fichiers de b octets prennent chacune beaucoup, beaucoup plus longtemps qu'une seule opération sur un seul fichier de n * - b octets. Cela est également vrai, par exemple pour les E/S disque.

Si vous regardez attentivement, vous verrez que le taux de transfert dans ce cas est size_of_the_file/secs.

Pour transférer des fichiers plus efficacement, regroupez-les avec tar, puis transférez l'archive tar:

tar cvf myarchive.tar cap_20151023T*.png

ou, si vous souhaitez également compresser l'archive,

tar cvzf myarchive.tar.gz myfile*

La compression ou non dépend du contenu du fichier, par exemple. s'il s'agit de fichiers JPEG ou PNG, la compression n'aura aucun effet.

15
dr_

Une autre raison pour laquelle scp est plus lent qu'il ne devrait l'être, en particulier sur les réseaux à large bande passante, est qu'il a des tampons de contrôle de flux internes définis statiquement qui finissent par devenir des goulots d'étranglement des performances du réseau.

HPN-SSH est une version corrigée d'OpenSSH qui augmente la taille de ces tampons. Cela fait une différence énorme avec la vitesse de transfert scp (voir les graphiques sur le site, mais je parle aussi d'expérience personnelle). Bien sûr, pour obtenir les avantages dont vous avez besoin pour installer HPN-SSH sur tous vos hôtes, cela en vaut la peine si vous devez régulièrement transférer des fichiers volumineux.

7
Menno Smits

J'ai utilisé la technique décrite ici qui utilise gzip parallèle et netcat pour compresser et copier rapidement les données.

Cela se résume à:

# SOURCE: 
> tar -cf - /u02/databases/mydb/data_file-1.dbf | pigz | nc -l 8888

# TARGET:
> nc <source Host> 8888 | pigz -d | tar xf - -C /

Cela utilise tar pour rassembler le ou les fichiers. Utilise ensuite pigz pour obtenir de nombreux threads cpu pour compresser et envoyer le fichier, la transmission réseau utilise netcat. Côté réception, netcat écoute puis décompresse (en parallèle) et décompresse.

6
Freiheit

Je viens d'avoir ce problème lors d'un transfert de site à site d'un gros fichier mp4 via scp. Obtient ~ 250 Ko/s. Après avoir désactivé la protection contre les inondations (FP) UDP sur le pare-feu de destination, le taux de transfert est passé à 6,5 Mo/s. Lorsque vous réactivez FP, le taux retombe à ~ 250 Ko/s.

Expéditeur: cygwin, Destinataire: Fedora 20, Firewall Sophos UTM.

Pourquoi SSH utilise-t-il UDP? @ Superuser.com - Ce n'est pas directement d'après ce que j'ai lu.

Lors de l'examen du journal du pare-feu, la détection des inondations se produisait à la fois sur les ports source et destination 4500 sur les adresses IP publiques, et non sur les adresses VPN internes de site à site privées. Il semble donc que mon problème soit probablement une NAT situation transversale où les données scp TCP sont finalement cryptées et encapsulées dans ESP & paquets UDP, et par conséquent soumis à FP. Pour supprimer scp de l'équation, j'ai exécuté une opération de copie de fichiers Windows sur le VPN et remarqué des performances similaires à scp avec et sans FP activé. A également exécuté un test iperf sur TCP et a remarqué 2Mbits/sec avec FP, et 55Mbits/sec sans.

Comment fonctionne NAT-T avec IPSec? @ Cisco.com

5
bvj

Étant donné que cette question n'est pas si ancienne et que personne d'autre n'a fait référence à cette solution, je pense qu'elle est appropriée car elle pousse la bande passante à la limite maximale (10 Mo/s dans mon cas) contrairement à scp qui est d'environ 250 ko/s, ce qui répond à votre question.

En fait, les mêmes 250 kb/s avec rsync - au moins avec le spécificateur de port rclone -Avvp cap_* -e "ssh -p 1087 -i id_rsa" user@Host:~/dir


Citer un publier sur la liste de diffusion openssh-unix-dev :

Le protocole scp est obsolète, rigide et difficile à corriger. Ses auteurs recommandent plutôt l'utilisation de protocoles plus modernes comme sftp et rsync pour le transfert de fichiers

La même syntaxe s'applique à sftp donc au lieu de scp text.txt user@Host c'est maintenant sftp text.txt user@Host ( exemples d'utilisation scp interchangeables avec sftp )

De plus, la version récente d'OpenSSH devrait activer le démon - au moins dans mon cas sur un serveur Arch Linux mais vous devrez peut-être installer un paquet sftp sur d'autres distributions.


Un autre exemple de travail avec un indicateur de fichier de chiffrement ssh (id_rsa) et un port ssh non standard 1087 au lieu de 22 pour vous éviter de jouer avec la syntaxe:

sftp -P 1087 -i id_rsa user@server:/home/user/Downloads/Video/*/*.mp4 /home/user/Videos/

Votre sftp peut également être limité à 800kb/s ou ~ 1 Mbit/s. Vous pouvez vérifier cela avec:

# sysctl -a | grep net.*rmem

et vous pouvez modifier les limites, par exemple comme ça s'ils sont trop lents:

   # sysctl -w net.ipv4.tcp_rmem='40960 873800 62914560'

   # sysctl -w net.core.rmem_max=8388608
0
Ivanovic