Je veux écrire un programme (sous Python 3.x sous Windows 7) qui exécute plusieurs commandes sur un shell distant via ssh. Après avoir examiné la fonction exec_command () de paramikos, je me suis rendu compte que ce n'était pas adapté à mon cas d'utilisation (car le canal se ferme après l'exécution de la commande), car les commandes dépendent de variables d'environnement (définies par des commandes précédentes) et ne peuvent pas être concaténés en un seul appel exec_command () car ils doivent être exécutés à des moments différents du programme.
Ainsi, je veux exécuter des commandes sur le même canal. L'option suivante que j'ai envisagée consistait à implémenter un shell interactif à l'aide de la fonction invoke_Shell () de paramikos:
ssh = paramiko.SSHClient()
ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(Host, username=user, password=psw, port=22)
channel = ssh.invoke_Shell()
out = channel.recv(9999)
channel.send('cd mivne_final\n')
channel.send('ls\n')
while not channel.recv_ready():
time.sleep(3)
out = channel.recv(9999)
print(out.decode("ascii"))
channel.send('cd ..\n')
channel.send('cd or_fail\n')
channel.send('ls\n')
while not channel.recv_ready():
time.sleep(3)
out = channel.recv(9999)
print(out.decode("ascii"))
channel.send('cd ..\n')
channel.send('cd simulator\n')
channel.send('ls\n')
while not channel.recv_ready():
time.sleep(3)
out = channel.recv(9999)
print(out.decode("ascii"))
ssh.close()
Il y a quelques problèmes avec ce code:
Je suis confondu avec ce "non-déterminisme" et j'apprécierais beaucoup votre aide.
import paramiko
import re
class ShellHandler:
def __init__(self, Host, user, psw):
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
self.ssh.connect(Host, username=user, password=psw, port=22)
channel = self.ssh.invoke_Shell()
self.stdin = channel.makefile('wb')
self.stdout = channel.makefile('r')
def __del__(self):
self.ssh.close()
def execute(self, cmd):
"""
:param cmd: the command to be executed on the remote computer
:examples: execute('ls')
execute('finger')
execute('cd folder_name')
"""
cmd = cmd.strip('\n')
self.stdin.write(cmd + '\n')
finish = 'end of stdOUT buffer. finished with exit status'
echo_cmd = 'echo {} $?'.format(finish)
self.stdin.write(echo_cmd + '\n')
shin = self.stdin
self.stdin.flush()
shout = []
sherr = []
exit_status = 0
for line in self.stdout:
if str(line).startswith(cmd) or str(line).startswith(echo_cmd):
# up for now filled with Shell junk from stdin
shout = []
Elif str(line).startswith(finish):
# our finish command ends with the exit status
exit_status = int(str(line).rsplit(maxsplit=1)[1])
if exit_status:
# stderr is combined with stdout.
# thus, swap sherr with shout in a case of failure.
sherr = shout
shout = []
break
else:
# get rid of 'coloring and formatting' special characters
shout.append(re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]').sub('', line).
replace('\b', '').replace('\r', ''))
# first and last lines of shout/sherr contain a Prompt
if shout and echo_cmd in shout[-1]:
shout.pop()
if shout and cmd in shout[0]:
shout.pop(0)
if sherr and echo_cmd in sherr[-1]:
sherr.pop()
if sherr and cmd in sherr[0]:
sherr.pop(0)
return shin, shout, sherr
J'utilise fondamentalement tout votre code et je viens d'ajouter une boucle for:
commands = ["ls","command2","command3"]
conn_one = ShellHandler(Host,name,pwd)
for command in commands:
conn_one.execute(command)
Il exécute 2 des commandes avec la sortie correcte, mais reste alors là. Je me demande si je dois appeler del quelque part dans le code.