Émetteur et le récepteur pour transférer des fichiers via ssh sur demande?
-
21-08-2019 - |
Question
J'ai créé un programme qui itère sur un tas de fichiers et invoque pour certains d'entre eux:
scp <file> user@host:<remotefile>
Cependant, dans mon cas, il peut y avoir des milliers de petits fichiers qui doivent transférer et scp est l'ouverture d'une nouvelle connexion ssh pour chacun d'eux, qui a tout à fait certains frais généraux.
Je me demandais s'il n'y a pas de solution où je garde un fonctionnement de processus qui maintient la connexion et je peux l'envoyer « demandes » à copier sur un seul fichier.
Idéalement, je suis à la recherche d'une combinaison de certains programmes d'émetteur et le récepteur, de sorte que je peux commencer un processus unique (1) au début:
ssh user@host receiverprogram
Et pour chaque fichier, j'invoque une commande (2):
senderprogram <file> <remotefile>
et le tuyau de la sortie (2) à l'entrée (1), et cela causerait le fichier à transférer. En fin de compte, je peux envoyer procédé (1) un certain signal fin.
De préférence, le programmes émetteur et récepteur sont des programmes C open source pour Unix. Ils peuvent communiquer à l'aide d'une prise à la place d'un tuyau ou toute autre solution de création.
Cependant, il est une contrainte important que chaque fichier est transféré au moment où j'itérer dessus: il n'est pas acceptable de recueillir une liste de fichiers, puis invoquer une instance de à scp
transférer tous les fichiers à la fois à la fin. Aussi, j'ai seulement simple accès shell à l'hôte de réception.
Mise à jour: J'ai trouvé une solution pour le problème de la connexion en utilisant en tête les caractéristiques de multiplexage de ssh, voir ma réponse ci-dessous. Et pourtant, je commence une prime parce que je suis curieux de savoir s'il existe un programme émetteur / récepteur que je décris ici. Il semble qu'il devrait exister quelque chose qui peut être utilisé, par exemple xmodem / ymodem / zmodem?
La solution
De cette façon fonctionnerait, et pour d'autres choses, cette approche générale est plus ou moins droite.
(
iterate over file list
for each matching file
echo filename
) | cpio -H newc -o | ssh remotehost cd location \&\& | cpio -H newc -imud
Autres conseils
J'ai trouvé une solution sous un autre angle. Depuis la version 3.9 , supports OpenSSH multiplexage Session : une seule connexion peut effectuer plusieurs sessions de connexion ou de transfert de fichiers. Cela permet d'éviter le coût d'installation par connexion.
Dans le cas de la question, je peut d'abord établir une connexion avec établit un maître de commande (-M
) avec une douille (-S
) dans un emplacement spécifique. Je ne ai pas besoin d'une session (-N
).
ssh user@host -M -S /tmp/%r@%h:%p -N
Ensuite, je peux invoquer pour chaque fichier scp
et des instructions pour utiliser le même socket:
scp -o 'ControlPath /tmp/%r@%h:%p' <file> user@host:<remotefile>
Cette commande commence à copier presque instantanément!
Vous pouvez également utiliser la prise de contrôle pour les connexions ssh normales, qui sera ensuite ouvrir immédiatement:
ssh user@host -S /tmp/%r@%h:%p
Si la prise de commande est plus disponible (par exemple parce que vous avez tué le maître), ce revient à une connexion normale. Plus d'informations sont disponibles dans cet article .
Il pourrait fonctionner à utiliser sftp au lieu de scp et de le placer en mode batch. Faites la commande batch fichier ou un tube UNIX socket de domaine et d'alimentation des commandes à ce que vous voulez les faire exécuter.
Sécurité sur cette question pourrait être un peu délicat à la fin du client.
Avez-vous essayé sshfs
?
Vous pouvez:
sshfs remote_user@remote_host:/remote_dir /mnt/local_dir
Où
-
/remote_dir
est le répertoire que vous voulez envoyer des fichiers sur le système à vous dans l'exécution de ssh -
/mnt/local_dir
était l'emplacement de montage local
Avec cette configuration, vous pouvez simplement un fichier dans cp
le et il serait local_dir
être envoyé sur à sftp
dans son remote_host
remote_dir
Notez qu'il ya une seule connexion, donc il y a peu de la manière des frais généraux
Vous devrez peut-être utiliser le drapeau pour maintenir un -o ServerAliveInterval=15
installé localement fuse
et un serveur SSH supportant (et configuré pour) <=>
Peut être que vous recherchez ceci: zssh
zssh (Zmodem SSH) est un programme interactif destiné à transférer des fichiers sur un ordinateur distant en utilisant le shell sécurisé (SSH). Il est destiné à être une alternative pratique à scp, ce qui permet de transférer des fichiers sans avoir à ouvrir une autre session et se ré-authentifier.
Utilisez rsync sur ssh si vous pouvez rassembler tous les fichiers à envoyer dans un seul répertoire (ou la hiérarchie des répertoires).
Si vous n'avez pas tous les fichiers dans un seul endroit, s'il vous plaît donner plus d'informations sur ce que vous voulez réaliser et pourquoi vous ne pouvez pas emballer tous les fichiers dans une archive et l'envoyer plus. Pourquoi est-il si important que chaque fichier est envoyé immédiatement? Serait-il OK si le fichier a été envoyé avec un court délai (comme lorsque 4K valeur de données a accumulé)?
Il est un joli petit problème. Je ne suis pas au courant d'une solution préemballée, mais vous pouvez faire beaucoup avec des scripts shell simples. Je vais essayer ceci au récepteur:
#!/bin/ksh
# this is receiverprogram
while true
do
typeset -i length
read filename # read filename sent by sender below
read size # read size of file sent
read -N $size contents # read all the bytes of the file
print -n "$contents" > "$filename"
done
Du côté de l'expéditeur, je créerais un tube nommé et lire de la conduite, par exemple.
mkfifo $HOME/my-connection
ssh remotehost receiver-script < $HOME/my-connection
Ensuite, pour envoyer un fichier que je vais essayer ce script
#!/bin/ksh
# this is senderprogram
FIFO=$HOME/my-connection
localname="$1"
remotename="$2"
print "$remotename" > $FIFO
size=$(stat -c %s "$localname")
print "$size" > $FIFO
cat "$localname" > $FIFO
Si la taille du fichier est grande que vous ne voulez probablement pas le lire d'un seul coup, donc quelque chose de l'ordre de
BUFSIZ=8192
rm -f "$filename"
while ((size >= BUFSIZ)); do
read -N $BUFSIZE buffer
print -n "$buffer" >> "$filename"
size=$((size - BUFSIZ))
done
read -N $size buffer
print -n "$contents" >> "$filename"
Finalement, vous aurez envie d'étendre le script afin que vous puissiez passer à travers et chmod
commandes chgrp
. Puisque vous faites confiance le code d'envoi, il est plus facile de structurer probablement la chose pour que le récepteur appelle simplement shell sur chaque ligne eval
, puis envoyer des choses comme
print filename='"'"$remotename"'"' > $FIFO
print "read_and_copy_bytes " '$filename' "$size" > $FIFO
et ensuite définir une fonction locale read_and_copy_bytes
. Obtenir le droit de citer est un ours, mais sinon il devrait être simple.
Bien sûr, rien de tout cela a été testé! Mais j'espère que cela vous donne quelques idées utiles.
On dirait un emploi pour le goudron? Tuyau sa sortie à ssh, et de l'autre tuyau du côté de la sortie de ssh retour au goudron.
Je pense que le bureau GNOME utilise une connexion SSH unique lors de l'accès d'une part par le biais SFTP (SSH). Je devine que c'est ce qui se passe parce que je vois un processus SSH unique quand j'accéder à un partage à distance de cette façon. Donc, si cela est vrai, vous devriez être en mesure d'utiliser à cet effet le même programme.
La nouvelle version de GNOME utilisé GVFS par GIO afin d'effectuer tous type d'E / S à travers différents backends. Le paquet Ubuntu gvfs-bin fournit divers utilitaires de ligne de commande qui vous permettent de manipuler les backends de la ligne de commande.
D'abord, vous devrez monter votre dossier SSH:
gvfs-montage sftp: // user @ host /
Et vous pouvez utiliser la gvfs-copie pour copier vos fichiers. Je pense que tous les transferts de fichiers seront effectués par un seul processus SSH. Vous pouvez même utiliser ps pour voir quel processus est utilisé.
Si vous vous sentez plus aventureux, vous pouvez même écrire votre propre programme en C ou dans une autre langue de haut niveau qui fournit une API pour GIO.
L'une des options est Conch est une implémentation client et le serveur SSH écrit en Python en utilisant le < a href = "http://twistedmatrix.com/trac/" rel = "nofollow noreferrer"> cadre de Twsited. Vous pouvez l'utiliser pour écrire un outil qui accepte les demandes via un autre protocole (HTTP ou les sockets Unix domaine, FTP, SSH ou autre) et déclenche le transfert de fichiers sur une longue connexion SSH en cours d'exécution. En fait, j'ai plusieurs programmes de production qui utilisent cette technique pour éviter de multiples configurations de connexion SSH.
Il y avait très similaire question ici il y a quelques semaines. La réponse acceptée proposé d'ouvrir un tunnel lorsque ssh'ing à la machine à distance et d'utiliser ce tunnel pour les transferts scp.
CurlFtpFS pourrait être une solution valable pour vous.
On dirait qu'il monte juste un dossier de votre ordinateur externe à votre ordinateur via SFTP. Une fois cela fait, vous devriez être en mesure d'utiliser vos commandes régulières et tout sera cp
être fait en toute sécurité.
Malheureusement, je n'ai pas pu le tester moi-même, mais laissez-moi savoir si cela fonctionne pour toi!
Modifier 1: Je suis en mesure de télécharger et tester. Comme je le craignais, il ne nécessite que le client dispose d'un serveur FTP. Cependant , je l'ai trouvé un autre programme qui a exactement le même concept que ce que vous recherchez. Vous permet de sshfs
connecter à votre ordinateur client sans avoir besoin de serveur spécial. Une fois que vous avez monté un de ses dossiers, vous pouvez utiliser votre commande normale pour déplacer umount /path/to/mounted/folder
des fichiers que vous avez besoin de plus. Une fois que vous avez terminé, il devrait alors être une question de sourire de <=>. Permettez-moi de savoir comment cela fonctionne!
rsync -avlzp user@remotemachine:/path/to/files /path/to/this/folder
utilisera SSH pour transférer des fichiers, d'une manière non-lente
Keep it simple, écrire un petit script d'emballage qui fait quelque chose comme ça.
- tar les fichiers
- envoyer le goudron fichier
- untar de l'autre côté
Quelque chose comme ceci:
-
<> Li -cvzf goudron fichiers test.tgz ....
- scp test.tgz user@other.site.com:.
- ssh user@other.site.com tar -xzvf test.tgz
/ Johan