Skip to main content
Dans mon dernier blog, j'ai parlé de l'automatisation des transferts de fichiers par FTP. L'utilisation du FTP pose trois problèmes. Premièrement, votre mot de passe est envoyé en clair sur le réseau, ce qui le rend accessible à toute personne disposant d'un analyseur de protocole. Deuxièmement, vos données sont également envoyées en texte clair. Troisièmement, vous devez enregistrer votre mot de passe quelque part sur le module, soit dans la macro, soit dans le fichier .netrc. En raison de ces problèmes, de nombreux sites ont imposé ou envisagent d'imposer l'utilisation du SFTP, le sous-système FTP sécurisé de SSH, à la place du FTP. Cependant, vous ne pouvez tout simplement pas remplacer ftp par sftp dans votre macro de commande (figure 1) et vous attendre à ce que cela fonctionne (figure 2).

 

&attach_input
sftp 172.16.1.116
nd
MYPASSWORD
put foo
&if (command_status) ^= 226 &then &goto ERROR1
get bar
&if (command_status) ^= 226 &then &goto ERROR2
quit
&
&label ERROR1
..display_line Could not put file
quit
&return
&
&label ERROR2
..display_line Could not get file
quit
&return

Figure 1 - sftp1.cm - remplacement de la commande ftp par sftp dans une macro de commande

 

sftp1
Connecting to 172.16.1.116...
dup2: Bad file number.
Error on line 3 of sftp1.
command_processor: Object not found. nd. In command macro
%phx_vos#m15_mas>SysAdmin>Noah_Davids>sftp1.cm
ready  12:39:59

 

Figure 2 - sftp1.cm
Le problème est une incompatibilité entre la façon dont les commandes VOS natives et l'open source POSIX traitent les entrées. Cependant, le SFTP, comme le FTP, permet de créer un fichier avec une liste de requêtes (figure 3) qu'il va exécuter automatiquement (figure 4).

 


put foo
get bar

 

Figure 3 - sftp2.input - fichier contenant les demandes d'exécution de sftp

 


sftp -b sftp2_input nd@172.16.1.116
nd@172.16.1.116's password:
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/foo
sftp> get bar
Couldn't stat remote file: No such file or directory
File "/SysAdmin/Noah_Davids/bar" not found.
Ready  13:06:45

 

Figure 4 - exécution avec un fichier de demandes en entrée et une invite de mot de passe
Vous remarquerez dans la figure 4 que sftp demande un mot de passe. Il est impossible de mettre le mot de passe dans le fichier d'entrée. La SEULE façon de contourner l'invite de mot de passe est d'utiliser l'authentification par clé publique (figure 5).

 

sftp -b sftp2_input nd@172.16.1.116
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/foo
sftp> get bar
Couldn't stat remote file: No such file or directory
File "/SysAdmin/Noah_Davids/bar" not found.
Ready  13:12:28

 

Figure 5 - exécution avec un fichier d'entrée des demandes, en utilisant l'authentification par clé publique pour éliminer l'invite de mot de passe

 

Vous trouverez un article sur la manière de mettre en place l'authentification à clé publique ici - http://members.cox.net/ndav1/self_published/publickey_authentication_setup.html

Malheureusement, sftp se contente d'exécuter toutes les requêtes du fichier d'entrée les unes après les autres, il n'y a pas de mécanisme permettant de tester si le transfert a fonctionné ou non.

Comme les macros de commande ne peuvent pas être utilisées, y a-t-il des alternatives ? Le produit gnu_tools est livré avec un programme appelé expect. Il peut être utilisé pour envoyer des commandes, attendre un nombre quelconque de réponses différentes et faire quelque chose en fonction de ce qu'il voit dans le flux de sortie. Je ne suis pas un expert en expect, mais le script de la figure 6 vous aidera à démarrer. Si vous cherchez sur le web des "scripts expect", vous trouverez de nombreuses références qui vous aideront à personnaliser mon exemple simple.

 

# If we get an end-of-file (eof) it means that the sftp process
# terminated. Report the last command that was sent.
#
proc goteof {cmd} {
puts "sftp connection unexpectedly closed n"
puts "last text received wasn"
puts "<<"
puts $cmd
puts ">>nnn"
exit
}
# Cette procédure fait des correspondances d'expression régulière en recherchant des chaînes de caractères clés
# dans la sortie collectée de la commande qui a été exécutée. Dans ce cas
# Je ne fais que signaler le type d'erreur, mais d'autres choses peuvent être faites
# aussi. Je ne vérifie également que deux erreurs. Il y en a d'autres. Vous aurez
# pour les ajouter au fur et à mesure que vous les trouvez.
#
proc checkforerrors {buf cmd} {
if [regexp {.*not found} $buf] {
met "$cmd FAILED : not foundnnn"
retour 1
}
if [regexp {.*Permission refusée} $buf] {
met "$cmd FAILED : problèmes d'accèsnnn
retour 1
}
retour 0
}# Réglez le délai d'attente sur -1 pour qu'il n'y ait pas de délai d'attente. La valeur par défaut est de 10 secondes
# et la plupart des transferts de fichiers prennent plus de temps que cela. J'ai décidé de ne pas mettre
# timeout, vous pouvez changer ça.
régler le délai d'attente -1

# start sftp
spawn sftp nd@172.16.1.116

# attendre l'invite sftp mais si nous obtenons une invite d'authentification, se terminant par
# oui/non, signaler un problème de sécurité et quitter.
attend {
"oui/non ?" { puts
"nnnNous nous sommes connectés au mauvais serveur ou le serveur a été rechargé".
puts
"La clé du serveur doit être validée avant que ce script puisse être exécuté à nouveau.nnn"
exit }
sftp>
}

# changer de répertoire pour les tests
send "cd sftp_testr"
expectant {
eof { goteof "cd sftp_test" }
sftp>
}

# appeler vérifier les erreurs en passant tous les caractères collectés jusqu'à l'
# sftp> prompt. Aussi la commande qui a été envoyée à sftp. Si la procédure
# checkforerrors renvoie 1, quittez le script. Encore une fois, vous pouvez
# faire d'autres choses.
si {[checkforerrors $expect_out(buffer) "cd sftp_test"] == 1} { exit }

send "put foor" (mettre le pied)
expectation {
eof { goteof "put foo" }
sftp>
}
si {[checkforerrors $expect_out(buffer) "put foo"] == 1} { exit }

send "get barr"
expectation {
eof { goteof "get bar" }
sftp>
}
if {[checkforerrors $expect_out(buffer) "get bar"] == 1} { exit }

envoyer "quitr
attendre eof
met "script donenn

 

Figure 6 - sftp3.exp - le script devrait automatiser le SFTP

 

expect sftp3.exp
spawn sftp nd@172.16.1.116
Connecting to 172.16.1.116...
The authenticity of host 172.16.1.116(172.16.1.116)' can't be established
+.
RSA key fingerprint is 37:f4:1a:56:64:af:ab:8a:7c:0b:36:47:c5:6c:1d:1a.
Are you sure you want to continue connecting (yes/no)?
Nous nous sommes connectés au mauvais serveur ou le serveur a été rechargé.
La clé du serveur doit être validée avant que ce script puisse être exécuté à nouveau. ready 10:41:10

 

Figure 7 - Exécution du script sftp3.exp expect avec avertissement de sécurité

 

expect sftp3.exp
spawn sftp nd@172.16.1.116
Connecting to 172.16.1.116...
sftp> cd sftp_test
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/sftp_test/foo
sftp> get bar
Impossible de statuer sur le fichier distant : Aucun fichier ou répertoire de ce type
Fichier "/SysAdmin/Noah_Davids/sftp_test/bar" non trouvé.
sftp> get bar FAILED : not foundready 10:42:11

 

Figure 8 - Exécution du script sftp3.exp sans avertissement mais avec un transfert échoué

Enfin, dans mon blog FTP, j'ai mentionné que le FTP était capable de lire des fichiers qui étaient encore ouverts et que cela a parfois entraîné le transfert de fichiers incomplets. J'ai suggéré que si la macro FTP attend qu'un fichier apparaisse à un endroit puis le transfère, la macro devrait vérifier qu'il n'est plus verrouillé. Le même problème peut se produire avec le SFTP et la solution est la même. Vous pouvez placer la vérification du verrouillage du fichier dans une macro de commande (figure 9) et ensuite, lorsque le fichier n'est plus verrouillé, appelez la fonction "Attendre" avec le script approprié.

&label AGAIN
&if (exists new_file) = 1 & (locked new_file) = 0 &then &goto EXPECT
display_line new_file not ready for transfer as of (time)
sleep -seconds 15
&goto AGAIN
&
&
&label EXPECT
expect sftp3.exp

 

Figure 9 - Test de la macro de commande pour le verrouillage des fichiers avant d'appeler expect

2020 Stratus Technologies.