Vous n'êtes pas identifié.
Bonjour,
Dans le cadre d'un projet, je dois transférer plusieurs fichiers par SFTP.
Voila la fonction que j'ai crée (plus ou moins bien faite, n'étant pas expert en shell... )
Je développe en ksh
sftpUploadFile() { if [ $# -ne 4 ]; then echo "sftpUploadFile() : Appel incorrect" echo "usage : sftpUploadFile <rmt_host> <rmt_dir> <file> <log_file>" else RMT_HOST=${1} RMT_DIR=${2} FICHIER=${3} FIC_LOG=${4} fi sftp ${RMT_HOST} 2>>${FIC_LOG} >>${FIC_LOG} <<END_SFTP_SESSION cd ${RMT_DIR} mput ${FICHIER} END_SFTP_SESSION CR=$? if [ ! ${CR} -eq ${RC_OK} ]; then doLog "${szMsgERROR}" "La connexion au serveur distant a échouée (CR : $CR)" finScriptError fi }
Et donc à chaque fichier de la liste, j'appel cette fonction. Ce qui veut dire une ouverture de session pour chaque ce qui n'est vraiment pas terrible je vous l'accorde.
J'essaie donc de trouver le bout de code qui me manque pour boucler sur une liste de fichiers une fois la session ouverte :
Un peu comme ça :
sftp ${RMT_HOST} 2>>${FIC_LOG} >>${FIC_LOG} <<END_SFTP_SESSION cd ${RMT_DIR} cat ${LIST} | while read ${FICHIER} do mput ${FICHIER} done END_SFTP_SESSION
Mais ca ne fonctionne pas, puisque c'est le shell distant (sftp) qui essaie d'interpréter ces commandes, ce qui est compréhensible.
Alors comment faire ? La solution scp m'a déjà été proposée mais n'est pas possible (Contraintes projet)
Je vous remercie par avance
Dernière modification par Nick56 (19 Dec 2008 09:48:06)
Hors ligne
Bonjour,
Je suis tout nouveau sur ce forum, mais ce poste m'a interpelé! ;)
Une solution est de générer un fichier sh temporaire comme suit:
LISTE=... REMOTE_HOST=... FICHIER_TMP=sftp-multi.tmp.sh echo "sftp "${REMOTE_HOST}" <<END_SFTP_SESSION" > ${FICHIER_TMP} cat ${LISTE} | while read FICHIER do echo "mput "${FICHIER} >> ${FICHIER_TMP} done echo "END_SFTP_SESSION" >> ${FICHIER_TMP} sh ${FICHIER_TMP} rm ${FICHIER_TMP}
Une autre idée quelqu'un ?
Hors ligne
Merci jonathan, ça peut-être une solution effectivement, seulement, la création de script généré par un autre script, je suis moyennement chaud
Je suis sur d'avoir déjà vu une solution, mais alors, impossible de remettre la main dessus
Hors ligne
Hello,
Tu devrais pouvoir te passer du fichier temporaire avec un tube. Pour reprendre ta syntaxe (je ne suis pas très à l'aise avec ksh):
cat ${LISTE} | while read FICHIER do echo "mput ${FICHIER}" done | sftp $REMOTE_HOST
Avec les () pour le subshell en bash (j'imagine que ksh les supporte aussi), pour avoir un préambule de session:
( echo "cd dir" while read FILE do echo "put $FILE" done ) | sftp -b - $HOST
Evidemment, la solution propre serait d'avoir recours à scp, ou à rsync.
En dernier recours, si c'est juste l'aspect performance qui te gène, et que tu as un SSH récent, tu peux utiliser le multiplexage de connexion pour annuler le cout des appels répétés à sftp: (c'est de mémoire, y'a ptet des détails à changer)
ssh -fNM -S /tmp/sftp-sock-$HOST $HOST # ouvrir une connexion maître en background .. blah blah .. sftp -o 'ControlPath /tmp/sftp-sock-$HOST $HOST' ...blah blah... .. blah blah .. ssh -S /tmp/sftp-sock-$HOST -O exit
ca ne t'épargnera pas l'établissement de la session sftp, mais tu échappes au handshake TCP et SSH, ce qui d'expérience est le principal responsable de la latence.
Edit: sftp -b -
Hors ligne
Merci pour ses réponses BOFH, je vais tester ça sous peu.
Comme je l'ai dit, scp je ne peux pas l'utiliser (contrainte projet), tout comme rsync. De plus, la commande n'est pas vraiment adaptée.
Je ne connais pas bien scp, mais il me semble que l'ont peut uploader tout le contenu d'un répertoire avec une expression régulière (ex : *.a). Sauf que dans mon cas, c'est inutilisable :
- tous mes fichiers arrivent dans le même répertoire
- tous ne doivent pas être transférés au même moment
- impossible de les différencier par expression régulière
Hors ligne
Mhh, peux-tu en dire plus sur les contraintes de ton projet ? Je ne suis pas sur de comprendre le problème précis.
A priori, sftp est plus fait pour l'utilisation interactive que pour le traitement de masse. Et n'importe quel système qui dispose de sftp devrait aussi disposer de scp. Pour autant que je sache, les deux offrent les mêmes garanties de sécurité.
En quoi faire arriver tous les fichiers dans le même répertoire serait-il un problème ?
Pour ce qui est de la différenciation par globs (les regexp c'est autre chose), seuls des critères relativement farfelus sur les noms de fichiers peuvent la rendre impossible. Et même si c'était le cas, il est tout a fait possible de faire appel a un programme tiers pour filtrer la liste de noms avant de la passer à scp, avec une utilisation constructive de xargs et consorts.
Si on regarde ta première tentative de script avec sftp, elle se traduit simplement par:
scp ${LIST} ${RMT_HOST}:${RMT_DIR}
Hors ligne
Oui, c'est vrai (pas bien réveillé aujourd'hui). Seulement, je ne peux faire autrement, c'est une contrainte de la MOA qui exige l'usage du SFTP et du partenaire qui traite les fichiers. Parfois, il faut pas chercher à comprendre
Dernière modification par Nick56 (22 Dec 2008 10:07:23)
Hors ligne
Ah, si c'est pour envoyer des fichiers chez un tiers, c'est compréhensible. Le partenaire ne veut probablement pas vous donner accès a un shell, et restreindre ssh à l'usage de sftp est la manière la plus directe d'y arriver.
Maintenant, si le partenaire est prêt a discuter, il peut y avoir d'autres pistes intéressantes. Par exemple, il existe un outil, "scponly", qui fonctionne comme un shell restreint et permet de donner accès à la fois à scp et sftp, sans donner directement accès a un shell.
L'approche qui s'applique à sftp peut aussi s'appliquer à rsync, il suffit de forcer rsyncd au lieu de sftp-server.
Note aussi que rsync peut aussi fonctionner sans ssh, et donc en excluant complètement l'accès à un shell. Tu perds en revanche l'authentification et le chiffrement, qu'il faudra récupérer en utilisant par exemple SSL, ou simplement SSH avec un port-forwarding et /bin/false à la place du shell.
Voila voila, bonne chance pour ton projet !
Hors ligne
Je te remercie pour toutes ces infos fortes intéressantes. J'espère faire un retour d'ici peu, ces temps-ci, j'ai plusieurs projets en cours, et il faut que je priorise tout ça. La solution que j'avais indiquée (multiples connexions) est déjà en prod depuis un moment. Néanmoins, elle ne me satisfait pas.
Hors ligne
Petit retour plus d'un mois après.
ce petit bout de code fonctionne très bien
( echo "cd dir" while read FILE do echo "put $FILE" done ) | sftp -b - $HOST
Merci encore
(c'était peut-être pas utile de remonter le poste ^^)
Hors ligne