Besoin d'aide script en bash (transfert ssh multific d'un coup)
gnugo
-
Flachy Joe Messages postés 2303 Statut Membre -
Flachy Joe Messages postés 2303 Statut Membre -
Bonjour,
Je cherche à faire un script qui va transférer des fichiers (passés en argument) d'un serveur à un autre en utilisant SSH.
Le problème c'est que je voudrais compresser ces fichiers à la volée avant de les transférer mais également les enregistrer compressés sur le serveur de destination.
Petit "schéma" :
Serveur départ --SSH-- Serveur 1 -- SSH -- Serveur 2 -- SSH -- Serveur arrivée
fic1,fic2,... ===================================> fic1.gz,fic2.gz
C'est évidemment faisable par une simple boucle sur la liste des fichiers
Du genre for fic in $*; do cat $fic | gzip | ssh serv1 "ssh serv2 'ssh serv_final cat >$fic.gz'"; done
Mais cette manière de faire est très très lente car elle ouvre 1 tunnel ssh pour chaque fichier
Je souhaite donc les transférer tous en même temps.
Par exemple en faisant une archive, ce serait éventuellement possible : on fait un tar compressé de tous les fichiers que l'on envoie dans le pipe SSH.
Mais en faisant cela, j'obtiens une archive compressée alors que je veux chaque fichier compressé individuellement.
On pourrait très bien extraire l'archive puis tout rezipper... mais ça revient à compresser 2 fois et ça ce n'est absolument pas performant, voire idiot sur le principe.
Auriez-vous une idée à me suggèrer ? Je ne trouve de meilleure façon de faire... sauf à reecrire tout un programme d'archivage qui ferait une archive avec des fichiers compressés individuellement....
Merci d'avance :-D
Je cherche à faire un script qui va transférer des fichiers (passés en argument) d'un serveur à un autre en utilisant SSH.
Le problème c'est que je voudrais compresser ces fichiers à la volée avant de les transférer mais également les enregistrer compressés sur le serveur de destination.
Petit "schéma" :
Serveur départ --SSH-- Serveur 1 -- SSH -- Serveur 2 -- SSH -- Serveur arrivée
fic1,fic2,... ===================================> fic1.gz,fic2.gz
C'est évidemment faisable par une simple boucle sur la liste des fichiers
Du genre for fic in $*; do cat $fic | gzip | ssh serv1 "ssh serv2 'ssh serv_final cat >$fic.gz'"; done
Mais cette manière de faire est très très lente car elle ouvre 1 tunnel ssh pour chaque fichier
Je souhaite donc les transférer tous en même temps.
Par exemple en faisant une archive, ce serait éventuellement possible : on fait un tar compressé de tous les fichiers que l'on envoie dans le pipe SSH.
Mais en faisant cela, j'obtiens une archive compressée alors que je veux chaque fichier compressé individuellement.
On pourrait très bien extraire l'archive puis tout rezipper... mais ça revient à compresser 2 fois et ça ce n'est absolument pas performant, voire idiot sur le principe.
Auriez-vous une idée à me suggèrer ? Je ne trouve de meilleure façon de faire... sauf à reecrire tout un programme d'archivage qui ferait une archive avec des fichiers compressés individuellement....
Merci d'avance :-D
A voir également:
- Besoin d'aide script en bash (transfert ssh multific d'un coup)
- Script vidéo youtube - Guide
- Whatsapp transfert discussion - Accueil - WhatsApp
- Ssh download - Télécharger - Divers Web & Internet
- Ghost script - Télécharger - Polices de caractères
- Mas script - Accueil - Windows
5 réponses
Salut,
Tu compresses tes fichiers individuellement au départ :
Tu crées une archive tar à la volée que tu envoies via ssh et tu la détarres toujours à la volée dans le répertoire de ton choix :
Tu compresses tes fichiers individuellement au départ :
gzip *
Tu crées une archive tar à la volée que tu envoies via ssh et tu la détarres toujours à la volée dans le répertoire de ton choix :
tar zcf - * | ssh user@serveur 'cd /chemin/ ; tar xzf -'
hello
les fichiers sont compressés, envoyés dans base64 précédés d'une entête avec le nom, qui permet de recréer le fichier avec awk.
essayer ça:
les fichiers sont compressés, envoyés dans base64 précédés d'une entête avec le nom, qui permet de recréer le fichier avec awk.
essayer ça:
for F in * ; do echo ++++++++++++ $F.gz ; gzip -c $F | base64 ; done | ssh user@server "cd /dest ; awk '/^+++++++/ {f=$2; next} {print | \"base64 -d > \" f}"
(j'ai pas testé avec ssh, problèmes de " et de ',sûrement)
Merci!
Belle solution!
Je vais essayer de l'appliquer
Juste un regret, le base64 qui augmente la taille des données à transférer. J'aimerais bien m'en passer mais je suppose que awk aura du mal à lire du binaire ( et ça deviendrait dangereux car les caractères +++++ ne seraient plus réservés qu'à l'en-tête.
... peut être en donnant nom de fichier + taille en octets pour séparer mais ça me parait impossible vu qu'on ne connait pas la taille avant de zipper le fichier
...Le plus simple serait d'utiliser quelquechose de plus performant que base64 qui nous laisse un caractère non utilisé pour notre en-tête (au pire on pourra utiliser autre chose qu'awk à l'arrivée si la lecture de flux binaire pose problème).
Si vous avez une idée je suis preneur :) )
Encore merci !
Belle solution!
Je vais essayer de l'appliquer
Juste un regret, le base64 qui augmente la taille des données à transférer. J'aimerais bien m'en passer mais je suppose que awk aura du mal à lire du binaire ( et ça deviendrait dangereux car les caractères +++++ ne seraient plus réservés qu'à l'en-tête.
... peut être en donnant nom de fichier + taille en octets pour séparer mais ça me parait impossible vu qu'on ne connait pas la taille avant de zipper le fichier
...Le plus simple serait d'utiliser quelquechose de plus performant que base64 qui nous laisse un caractère non utilisé pour notre en-tête (au pire on pourra utiliser autre chose qu'awk à l'arrivée si la lecture de flux binaire pose problème).
Si vous avez une idée je suis preneur :) )
Encore merci !
Mais l'en-tête est envoyée avant le fichier et on ne peut pas connaitre la taille avant d'avoir zippé tout le fichier (pas question de l'écrire temporairement sur disque ou en mémoire, il doit partir le plus vite possible dans le flux par le pipe) :/
Ta 1ere solution est vraiment bonne je pense, il faudrait juste trouver mieux que ce base64 (idéalement un base255 qui utilise tous les caractères possibles sauf 1, par exemple le '\0', qu'on utilisera pour séparer l'en-tête)
Ta 1ere solution est vraiment bonne je pense, il faudrait juste trouver mieux que ce base64 (idéalement un base255 qui utilise tous les caractères possibles sauf 1, par exemple le '\0', qu'on utilisera pour séparer l'en-tête)
Inspire-toi de ceci:
Gates gave ^H sold you the windows.
GNU gave us the whole house.(Alexandrin)
johand@osiris: ~/tmp $ (tar -czf - *) | ssh localhost '(mkdir ~/brol; cd ~/brol ; tar -xzf -)'
Gates gave ^H sold you the windows.
GNU gave us the whole house.(Alexandrin)
Ça fait une archive compressée et ensuite on est obligé de décompresser l'archive pour ensuite recompresser les fichiers un par un.
C'est pour ça que je n'utilise pas d'archiveur comme tar qui ne permettent pas de faire cela.
Je cherche à obtenir des fichiers compressés individuellement sur le serveur d'arrivée, avec une compression faite une seule fois et sur le serveur de départ, le tout dans un seul flux ssh
Donc à aucun moment je ne suis censé décompresser :)
C'est pour ça que je n'utilise pas d'archiveur comme tar qui ne permettent pas de faire cela.
Je cherche à obtenir des fichiers compressés individuellement sur le serveur d'arrivée, avec une compression faite une seule fois et sur le serveur de départ, le tout dans un seul flux ssh
Donc à aucun moment je ne suis censé décompresser :)
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Une idée : installer un serveur de partage sur la destination et "l'entunneler" par ssh. https://www.howtoforge.com/nfs_ssh_tunneling
Tu peux définir directement le point de montage comme destination de la compression et tu t'embêtes pas à créer un pseudo protocole de transfert.
Tu peux définir directement le point de montage comme destination de la compression et tu t'embêtes pas à créer un pseudo protocole de transfert.
Avec sshfs il n'y a pas besoin de partage nfs :
Si tu veux faire transiter tes fichiers par plusieurs serveur, il faut monter le répertoire de destination sur le serveur 2 puis le point de montage du serveur 2 sur le serveur 1 et enfin monter le point de montage du serveur 1 sur le client. Les actions de montage pouvant se faire à travers ssh, tu peux tout mettre en place dans le script lancé sur le client.
sudo apt-get install sshfs
mkdir my_ssh #création du point de montage
sshfs user@server: ./my_ssh/ #montage
find . -maxdepth 1 -type f -print -exec bash -c "gzip -c '{}' > './my_ssh/{}.gz' &" \; #compressions asynchrones
fusermount -u ./my_ssh #démontage
rmdir ./my_ssh
Si tu veux faire transiter tes fichiers par plusieurs serveur, il faut monter le répertoire de destination sur le serveur 2 puis le point de montage du serveur 2 sur le serveur 1 et enfin monter le point de montage du serveur 1 sur le client. Les actions de montage pouvant se faire à travers ssh, tu peux tout mettre en place dans le script lancé sur le client.
Le souci c'est justement que je ne peux pas compresser tous les fichiers au départ car cela implique de les enregistrer sur le disque du serveur.
Il me faut impérativement cette compression à la volée d'où mon problème :/