Parallélisation de rsync


30

Je viens de déménager et j'ai découvert après quelques essais et erreurs que quelque part entre ma maison et mon serveur distant, il y avait une limitation en cours ... mais la limitation n'est pas très intelligente. Il limite uniquement les connexions individuelles. Donc, si je copie un fichier de 1 Go, il se déroulera gaiement à 150 kbps. Mais si j'initialise 10 copies, chacune d'entre elles ira à 150 kBps (c'est-à-dire que j'obtiens une bande passante agrégée beaucoup plus élevée sur plusieurs connexions).

J'utilise rsync assez souvent pour synchroniser certains grands ensembles de données du travail à la maison (heureusement sous la forme de nombreux fichiers). Existe-t-il un moyen de dire à rsync de télécharger en utilisant plusieurs connexions? Théoriquement, cela devrait être possible car, pour autant que je sache, rsync effectue d'abord une passe pour déterminer les changements nécessaires, puis effectue la transmission réelle. Points bonus s'il existe un moyen magique de dire à rsync de découper des fichiers individuels en N morceaux, puis de les recoller. Je crois que CuteFTP est en fait assez intelligent pour réussir cela.

Réponses:


13

J'ai juste eu un problème similaire à déplacer plusieurs To d'un NAS vers un autre NAS sans capacité de sauvegarde / restauration qui me permettrait d'alimenter simplement 1 jeu à l'autre.

J'ai donc écrit ce script pour exécuter 1 rsync pour chaque répertoire qu'il rencontre. Cela dépend de la possibilité de lister les répertoires sources (attention à échapper à ARG 3) mais je pense que vous pouvez définir cette étape avec un rsync non récursif qui vient de copier les fichiers et les répertoires au niveau approprié.

Il détermine également le nombre de rsync à exécuter en fonction du nombre de processeurs, mais vous voudrez peut-être le modifier.

L'autre option possible qui vient à l'esprit est la suivante: exécuter un rsync en mode --list-only.

Cela vous donnerait tous les fichiers qui doivent être mis à jour. Ensuite, exécutez 1 rsync pour chaque fichier de votre liste si vous avez utilisé xargs pour gérer le nombre de rsyncs que vous aviez, cela pourrait être très élégant. En fait probablement une solution plus élégante que mon petit script ici ...

#! /bin/bash
SRC_DIR=$1
DEST_DIR=$2
LIST=$3
CPU_CNT=`cat /proc/cpuinfo|grep processor |wc -l`
#  pseudo random heuristic
let JOB_CNT=CPU_CNT*4
[ -z "$LIST" ] && LIST="-tPavW --exclude .snapshot --exclude hourly.?"
echo "rsyncing From=$SRC_DIR To=$DEST_DIR DIR_LIST=$LIST"
mkdir -p /{OLD,NEW}_NAS/home
[ -z "$RSYNC_OPTS" ] && RSYNC_OPTS="-tPavW --delete-during --exclude .snapshot --exclude hourly.?"
cd $SRC_DIR
echo $LIST|xargs -n1 echo|xargs -n1 -P $JOB_CNT -I% rsync ${RSYNC_OPTS} ${SRC_DIR}/%/ ${DEST_DIR}/%/

2
Cela fonctionne - vous pouvez apporter de nombreuses améliorations à son fonctionnement, mais le concept d'utilisation de xargs pour paralléliser votre application est assez nouveau.
MattPark

6

GNU Parallel a une solution

J'ai déplacé 15 To à 1 Gbps et cela peut saturer le lien à 1 Gbps.

Ce qui suit démarrera un rsync par gros fichier dans src-dir vers dest-dir sur le serveur fooserver:

cd src-dir; find . -type f -size +100000 | \
parallel -v ssh fooserver mkdir -p /dest-dir/{//}\; \
  rsync -s -Havessh {} fooserver:/dest-dir/{}

Les répertoires créés peuvent se retrouver avec des autorisations incorrectes et les fichiers plus petits ne sont pas transférés. Pour corriger ceux qui exécutent rsync une dernière fois:

rsync -Havessh src-dir/ fooserver:/dest-dir/

1
Pourriez-vous coller la section "EXEMPLE: Parallélisation de rsync" dans votre réponse. Juste au cas où le lien se briserait à l'avenir.
picobit

3

Oui. Une telle fonctionnalité existe.

Il existe un utilitaire appelé pssh qui fournit les fonctionnalités décrites.

Ce package fournit des versions parallèles des outils openssh. Inclus dans la distribution:

  • SSH parallèle (pssh)
  • SCP parallèle (PSCP)
  • Rsync parallèle (prsync)
  • Nuke parallèle (pnuke)
  • Slurp parallèle (pslurp)

Je ne sais pas à quel point il est facile à installer, mais cela pourrait bien faire l'affaire!


26
Les utilitaires pssh sont utilisés pour répartir les commandes sur plusieurs serveurs, et ne font pas la même commande plusieurs fois sur un serveur. En particulier, prsync ne prend en charge que l'envoi d'un fichier sur votre machine locale vers plusieurs machines externes. Il ne prend pas en charge le téléchargement d'un fichier distant avec plusieurs connexions.
Derek Dahmer

1
Compte tenu du commentaire de @ DerekDahmer, l'affiche de cette réponse pourrait vouloir la retirer?
mc0e

3

Je ne peux pas commenter, j'ai donc ajouté une nouvelle réponse, avec un code un peu meilleur que le code précédent (agréable et intelligent).

Vérifiez la rsyncligne, car elle contient un ioniceajustement facultatif .

#!/bin/bash
start_time=$(date +%s.%N)
# Transfer files in parallel using rsync (simple script)
# MAXCONN: maximum number "rsync" processes running at the same time:
MAXCONN=6
# Source and destination base paths. (not need to end with "/")
SRC_BASE=/home/user/public_html/images
DST_BASE=user@hostname.domain.local:/home/user/public_html/images
RSYNC_OPTS="-ah --partial"
# Main loop:
for FULLDIR in $SRC_BASE/*; do
    NUMRSYNC=`ps -Ao comm | grep '^'rsync'$' | wc -l `
    while [ $NUMRSYNC -ge $MAXCONN ]; do
        NUMRSYNC=`ps -Ao comm | grep '^'rsync'$' | wc -l `
        sleep 1
    done
    DIR=`basename $FULLDIR`
    echo "Start: " $DIR
    ionice -c2 -n5 rsync $RSYNC_OPTS $SRC_BASE/${DIR}/ $DST_BASE/${DIR}/ &
    # rsync $RSYNC_OPTS $SRC_BASE/${DIR}/ $DST_BASE/${DIR}/ &
    sleep 5
done

execution_time=$(echo "$(date +%s.%N) - $start" | bc)
printf "Done. Execution time: %.6f seconds\n" $execution_time

2

On dirait que quelqu'un a écrit cet utilitaire pour vous. Il rompt le transfert en morceaux parallèles. C'est une meilleure implémentation que la version "gros fichier parallèle" répertoriée sous GNU Parallel:

https://gist.github.com/rcoup/5358786

De plus, lftp peut paralléliser les transferts de fichiers via ftp, ftps, http, https, hftp, fish, sftp. Souvent, l'utilisation de lftp présente certains avantages, car la gestion des autorisations, des accès restreints, etc. pour rsync peut être difficile.


Bien que cela fonctionne, cela peut provoquer une énorme quantité de fragmentation du disque rapidement, car vous n'utilisez pas simplement plusieurs connexions pour télécharger le même fichier.
bparker

1

Non. Une telle fonctionnalité n'existe pas. Vous pouvez diviser la synchronisation en plusieurs appels rsyncsi vous le souhaitez vraiment.

Je vous suggère de trouver tout ce qui fait cette limitation de débit et d'avoir une conversation sérieuse avec celui qui l'entretient / le gère.


4
Ces restrictions proviennent souvent de certains FAI comme Comcast. Bonne chance d'avoir toute sorte de conversation raisonnable avec eux.
James Moore

1

Je voulais transférer plusieurs répertoires (avec de nombreux fichiers) en même temps, j'ai donc créé ce petit script:

#!/bin/bash
# Transfer files in parallel using rsync (simple script)
# MAXCONN: maximum number "rsync" processes running at the same time:
MAXCONN=10
# Source and destination base paths. (not need to end with "/")
SRC_BASE=/home/sites
DST_BASE=user@example.com:/var/www
RSYNC_OPTS="--stats -ilrtpog"
# Main loop:
for FULLDIR in $SRC_BASE/*/; do
    NUMRSYNC=`ps -Ao comm | grep '^'rsync'$' | wc -l `
    while [ $NUMRSYNC -ge $MAXCONN ]; do
        NUMRSYNC=`ps -Ao comm | grep '^'rsync'$' | wc -l `
        sleep 10
    done
    DIR=`basename $FULLDIR`
    rsync $RSYNC_OPTS $SRC_BASE/${DIR}/ $DST_BASE/${DIR}/ & 
    sleep 1 
done
echo "Done."

J'ai fait ce script assez rapidement, alors veuillez le réviser et le tester avant de l'utiliser dans un environnement de production.


0

J'ai créé le script suivant pour télécharger de nombreux dossiers avec des images en parallèle. Vous l'exécutez avec d'abord la cible de synchronisation, puis tous les noms de dossier à copier.

#!/bin/sh

dest="$1"
shift

if [ "$dest" = "" ]; then
    echo "USAGE: $0 TARGET:/foo/bar <dir1> [dir2] [dir3]"
    exit 1
fi

RCol='\x1B[0m' # Text Reset
BYel='\x1B[1;33m';

for i in "$@"; do
    prefix=`printf "$BYel%50s:$RCol" "$i"`
    echo "$prefix * Starting $i"
    echo "$prefix -> syncing '$i/' to '$dest/$i/'"
    (rsync -rv "$i/" "$dest/$i/") 2>&1 | sed "s/^/$prefix /g" &
    sleep 0.5
done

echo "* Waiting for all to complete"
wait

Il préfixe le nom du dossier en jaune sur toutes les sorties de la console rsync pour le rendre joli.


-1

Aria2 est un bon programme client pour télécharger des données en utilisant de nombreuses connexions à partir de nombreux miroirs. Il ne prend pas en charge SFTP. J'ai donc installé un serveur FTP - vsftpd . Ma connexion 3G fonctionne à pleine puissance avec 5 connexions au serveur FTP.


1
Souhaitez-vous développer ce point pour rendre votre réponse utile?
Tog
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.