web-dev-qa-db-fra.com

Comment exécutez-vous plusieurs commandes en une seule session dans Paramiko? (Python)

def exec_command(self, command, bufsize=-1):
    #print "Executing Command: "+command
    chan = self._transport.open_session()
    chan.exec_command(command)
    stdin = chan.makefile('wb', bufsize)
    stdout = chan.makefile('rb', bufsize)
    stderr = chan.makefile_stderr('rb', bufsize)
    return stdin, stdout, stderr

Lors de l'exécution d'une commande dans paramiko, elle réinitialise toujours la session lorsque vous exécutez exec_command. Je veux pouvoir exécuter Sudo ou su et avoir toujours ces privilèges lorsque j'exécute une autre commande exec_command. Un autre exemple serait d'essayer d'exec_command ("cd /"), puis d'exécuter à nouveau exec_command et de le placer dans le répertoire racine. Je sais que vous pouvez faire quelque chose comme exec_command ("cd /; ls -l"), mais je dois le faire dans des appels de fonction séparés.

38
Takkun

Cas d'utilisation non interactifs

Ceci est un exemple non interactif ... il envoie cd tmp, ls puis exit.

import sys
sys.stderr = open('/dev/null')       # Silence silly warnings from paramiko
import paramiko as pm
sys.stderr = sys.__stderr__
import os

class AllowAllKeys(pm.MissingHostKeyPolicy):
    def missing_Host_key(self, client, hostname, key):
        return

Host = '127.0.0.1'
USER = ''
PASSWORD = ''

client = pm.SSHClient()
client.load_system_Host_keys()
client.load_Host_keys(os.path.expanduser('~/.ssh/known_hosts'))
client.set_missing_Host_key_policy(AllowAllKeys())
client.connect(Host, username=USER, password=PASSWORD)

channel = client.invoke_Shell()
stdin = channel.makefile('wb')
stdout = channel.makefile('rb')

stdin.write('''
cd tmp
ls
exit
''')
print stdout.read()

stdout.close()
stdin.close()
client.close()

Cas d'utilisation interactifs
Si vous avez un cas d'utilisation interactif, cette réponse n'aidera pas ... Personnellement, j'utiliserais pexpect ou exscript pour des sessions interactives.

36
Mike Pennington

À strictement parler, vous ne pouvez pas. Selon la spécification ssh:

Une session est une exécution à distance d'un programme. Le programme peut être un shell, une application, une commande système ou un sous-système intégré.

Cela signifie qu'une fois la commande exécutée, la session est terminée. Vous ne pouvez pas exécuter plusieurs commandes en une seule session. Ce que vous POUVEZ faire, cependant, est de démarrer un Shell distant (== une commande), et d'interagir avec ce Shell via stdin etc ... (pensez à exécuter un script python vs exécuter le interprète interactif)

18
Steven

Essayez de créer une chaîne de commande séparée par le caractère \n. Ça a marché pour moi. Pour. par exemple. ssh.exec_command("command_1 \n command_2 \n command_3")

13
Sandeep

Vous pouvez le faire en appelant Shell sur le client et en envoyant des commandes. Veuillez vous référer ici
La page contient du code pour python 3.5. J'ai un peu modifié le code pour qu'il fonctionne avec pythin 2.7. Ajouter du code ici pour référence

import threading, paramiko

strdata=''
fulldata=''

class ssh:
    Shell = None
    client = None
    transport = None

    def __init__(self, address, username, password):
        print("Connecting to server on ip", str(address) + ".")
        self.client = paramiko.client.SSHClient()
        self.client.set_missing_Host_key_policy(paramiko.client.AutoAddPolicy())
        self.client.connect(address, username=username, password=password, look_for_keys=False)
        self.transport = paramiko.Transport((address, 22))
        self.transport.connect(username=username, password=password)

        thread = threading.Thread(target=self.process)
        thread.daemon = True
        thread.start()

    def close_connection(self):
        if(self.client != None):
            self.client.close()
            self.transport.close()

    def open_Shell(self):
        self.Shell = self.client.invoke_Shell()

    def send_Shell(self, command):
        if(self.Shell):
            self.Shell.send(command + "\n")
        else:
            print("Shell not opened.")

    def process(self):
        global strdata, fulldata
        while True:
            # Print data when available
            if self.Shell is not None and self.Shell.recv_ready():
                alldata = self.Shell.recv(1024)
                while self.Shell.recv_ready():
                    alldata += self.Shell.recv(1024)
                strdata = strdata + str(alldata)
                fulldata = fulldata + str(alldata)
                strdata = self.print_lines(strdata) # print all received data except last line

    def print_lines(self, data):
        last_line = data
        if '\n' in data:
            lines = data.splitlines()
            for i in range(0, len(lines)-1):
                print(lines[i])
            last_line = lines[len(lines) - 1]
            if data.endswith('\n'):
                print(last_line)
                last_line = ''
        return last_line


sshUsername = "SSH USERNAME"
sshPassword = "SSH PASSWORD"
sshServer = "SSH SERVER ADDRESS"


connection = ssh(sshServer, sshUsername, sshPassword)
connection.open_Shell()
connection.send_Shell('cmd1')
connection.send_Shell('cmd2')
connection.send_Shell('cmd3')
time.sleep(10)
print(strdata)    # print the last line of received data
print('==========================')
print(fulldata)   # This contains the complete data received.
print('==========================')
connection.close_connection()
2
Nagabhushan S N
cmd = 'ls /home/dir'
self.ssh_stdin, self.ssh_stdout, self.ssh_stderr = self.ssh.exec_command(cmd)
print self.ssh_stdout.read()
cmd2 = 'cat /home/dir/test.log'
self.ssh_stdin2, self.ssh_stdout2, self.ssh_stderr2 = self.ssh.exec_command(cmd2)
print self.ssh_stdout2.read()
2
user2661518