Diffuser des archives tar entre serveurs sans stockage local
Pour copier un répertoire entre deux serveurs, redirigez une commande tar exécutée côté source, via
SSH, vers une commande tar exécutée côté destination. L’archive transite par votre ordinateur sans
être enregistrée comme fichier local. La destination a besoin d’espace pour les fichiers extraits, mais
aucun des deux serveurs n’a besoin d’espace pour une archive intermédiaire.
Le trajet est serveur source → votre ordinateur → serveur de destination. Votre ordinateur transporte l’intégralité du flux et doit rester connecté. Les serveurs n’ont pas besoin d’un accès SSH l’un à l’autre. Si les octets doivent contourner entièrement votre ordinateur, exécutez le transfert sur un hôte disposant de la connectivité et des identifiants nécessaires vers les serveurs.
SSH chiffre les communications avec chaque serveur. L’archive est déchiffrée dans le tube local puis chiffrée à nouveau pour la destination. Utilisez donc un ordinateur de confiance. Il est inutile d’ajouter un mot de passe OpenSSL à ce pipeline pour chiffrer le transport.
Préparer la source et la destination
Cet exemple copie app-data depuis le répertoire personnel du compte source vers un nouveau répertoire
app-data.incoming dans le répertoire personnel du compte de destination. Remplacez source-server et
destination-server par vos alias SSH ou vos adresses user@host. Adaptez les chemins dans les deux
scripts si vos données se trouvent ailleurs.
Vous avez besoin de Bash sur l’ordinateur qui exécute les scripts, ainsi que d’un accès OpenSSH à deux
comptes Linux disposant de GNU tar, GNU find et GNU sha256sum. Le compte source doit pouvoir lire
chaque fichier, et le compte de destination doit pouvoir créer le répertoire de réception et son
contenu. Configurez l’authentification par clé, chargez toute clé chiffrée dans votre agent SSH et
vérifiez les clés d’hôte des deux serveurs avant de commencer. Les commandes utilisent
BatchMode=yes : elles échouent donc au lieu de demander
un mot de passe ou une confirmation de clé d’hôte pendant un transfert.
Arrêtez les écritures dans le répertoire source jusqu’à la fin de la copie et de la vérification, ou lisez depuis un instantané cohérent. Pour une application web, cela inclut les téléversements et les tâches en arrière-plan. Utilisez la procédure de sauvegarde de la base de données pour ses données : copier avec tar les fichiers d’une base de données en cours d’exécution ne produit pas une sauvegarde cohérente de celle-ci. Ces commandes copient des fichiers. La configuration de l’application et la bascule du trafic sont des étapes distinctes.
Les exemples ont été testés avec Bash 5.1.16, GNU tar 1.34 et OpenSSH 8.9p1 sous Linux. L’étape de somme de contrôle utilise GNU find et coreutils. Il ne s’agit pas d’une recette de commandes pour macOS.
Diffuser vers un nouveau répertoire
Enregistrez ce script sous transfer.sh sur votre ordinateur et exécutez-le avec bash transfer.sh :
#!/usr/bin/env bash
set -euo pipefail
ssh -T -o BatchMode=yes source-server 'test -d app-data'
ssh -T -o BatchMode=yes destination-server 'mkdir app-data.incoming'
ssh -T -o BatchMode=yes source-server 'tar -cf - -C app-data .' |
ssh -T -o BatchMode=yes destination-server 'tar -xf - -C app-data.incoming'
printf 'Transfer completed; verify app-data.incoming before using it.\n'
La commande mkdir sans option échoue volontairement si le répertoire de réception existe déjà.
Choisissez un nouveau chemin pour une nouvelle tentative, ou inspectez puis supprimez d’abord le
répertoire d’un transfert échoué. Cela évite que l’exemple extraie des fichiers par-dessus un
répertoire d’application existant.
Comprendre les bases du streaming avec tar
Dans tar -cf -, c crée une archive et f - l’envoie sur la sortie standard. Dans tar -xf -, x
extrait l’archive lue depuis l’entrée standard. Il s’agit des mêmes opérations que celles couramment
écrites tar cf - et tar xf -.
-C app-data change le répertoire de travail de tar
avant qu’il n’archive .. Les membres ont donc des noms tels que ./uploads/photo.jpg, fichiers cachés
compris, plutôt qu’un préfixe de répertoire que vous devriez supprimer ensuite. Lors de l’extraction,
-C place ces membres sous app-data.incoming. Cette option ne crée pas ce répertoire.
-T désactive l’allocation d’un pseudo-terminal par SSH afin que la connexion puisse transporter
des données binaires. pipefail fait échouer le
pipeline si l’une des deux commandes SSH échoue. set -e arrête alors le script avant son message de
fin. Sans pipefail, un processus tar source peut échouer après avoir produit une archive extractible
alors que la destination se termine avec succès.
SSH renvoie le code de sortie de la commande distante, ce qui permet à
Bash de détecter cet échec.
Une exécution réussie affiche le message de fin et laisse l’arborescence copiée dans app-data.incoming. Une
exécution échouée peut y laisser des fichiers partiels. Ni un code de sortie nul ni le message de fin ne
prouvent qu’une source en cours de modification a été copiée de manière cohérente.
Vérifier les fichiers copiés
Laissez la source inchangée et enregistrez ce script sous verify.sh. Exécutez bash verify.sh après le
transfert :
#!/usr/bin/env bash
set -euo pipefail
ssh -T -o BatchMode=yes source-server \
'cd app-data && find . -type f -exec sha256sum -- {} +' |
ssh -T -o BatchMode=yes destination-server \
'cd app-data.incoming && sha256sum --check --strict -'
printf 'Regular-file checksums match.\n'
Ce script diffuse une liste de sommes de contrôle entre les serveurs, là encore sans l’enregistrer
localement. GNU sha256sum --check affiche
./filename: OK pour chaque fichier correspondant et échoue pour les fichiers manquants ou différents. GNU
find -exec … {} + renvoie également un échec si une commande
de somme de contrôle échoue. Le côté source de ce pipeline est donc vérifié. Attendez-vous au message
final uniquement lorsque les deux côtés réussissent.
La vérification relit chaque fichier ordinaire sur les deux serveurs. Elle suppose au moins un fichier ordinaire et vérifie le contenu des fichiers, et non les cibles des liens symboliques, les répertoires vides, les permissions, la propriété ou les fichiers supplémentaires côté destination. Il s’agit d’une recette de copie de répertoire, pas d’une sauvegarde complète du système : elle ne demande pas la préservation des ACL ni des attributs étendus. Vérifiez les métadonnées dont votre application a besoin avant de la basculer vers le répertoire copié.
Ajuster le transfert si nécessaire
Pour afficher la progression, installez pv sur votre ordinateur et insérez-le dans le pipeline de
transfert : ssh … | pv | ssh …. Conservez le pipeline dans le script avec pipefail. Le
manuel de pv décrit son compteur d’octets, le temps écoulé et le
débit de transfert. Sans taille totale connue du flux, il ne peut fournir ni pourcentage d’achèvement
significatif ni estimation significative du temps restant. Sa sortie mesure les octets qui traversent
le tube local, pas des fichiers vérifiés.
Si l’accès nécessite un hôte bastion, ajoutez -J bastion-host à chaque commande SSH des deux scripts.
Configurez aussi l’authentification et la vérification de la clé d’hôte pour cet hôte.
ProxyJump se connecte à la cible via le bastion, mais le tube entre les deux
commandes SSH s’exécute toujours sur votre ordinateur. Les paramètres d’identité et de port de l’hôte
de rebond doivent figurer dans votre configuration SSH, car les options de ligne de commande
s’appliquent généralement à la cible finale.
Pour des données compressibles sur une connexion limitée, remplacez tar -cf - par tar -czf - et
tar -xf - par tar -xzf -. Cette variante utilise
l’option --gzip de tar et nécessite gzip sur les
deux serveurs. Elle consomme du temps CPU et peut n’apporter que peu de gain pour des vidéos, des
images ou des archives déjà compressées. Mesurez avec vos fichiers et votre connexion avant de supposer
que ce sera plus rapide.
Résoudre les problèmes courants
- Permission refusée ou disque plein : Lisez stderr des deux commandes SSH. Vérifiez que la source est lisible, ainsi que les permissions de destination, l’espace libre et les inodes disponibles. Corrigez la cause et repartez d’un nouveau répertoire de réception. N’utilisez pas une copie partielle.
- « File changed as we read it » : Arrêtez le processus qui écrit ou utilisez un instantané, puis répétez le transfert et la vérification des sommes de contrôle. Masquer l’avertissement ne peut pas rendre cohérente une copie à chaud.
- Erreurs d’archive inattendues : Les fichiers de démarrage du shell distant ne doivent pas
afficher de message d’accueil sur stdout pour les commandes non interactives. Cette sortie entrerait
dans le flux d’archive. Gardez les diagnostics sur stderr et ne fusionnez pas stderr dans le tube
avec
2>&1ou|&. - Connexion interrompue : Ce flux tar ne permet aucune reprise.
tmuxouscreenpeut maintenir un processus en cours d’exécution lorsque vous vous détachez de son terminal, mais ne peut pas réparer une connexion SSH rompue dans le pipeline de transfert. Recommencez dans un nouveau répertoire et vérifiez-le avant de l’utiliser.
