web-dev-qa-db-fra.com

Effectuer des commandes sur SSH avec Python

J'écris un script pour automatiser certaines commandes de ligne de commande en Python. En ce moment, je fais les appels suivants:

cmd = "some unix command"
retcode = subprocess.call(cmd,Shell=True)

Cependant, j'ai besoin d'exécuter des commandes sur une machine distante. Je me connecterais manuellement à l’aide de ssh, puis jetterais les commandes. Comment pourrais-je automatiser cela en Python? Je dois me connecter avec un mot de passe (connu) à la machine distante. Je ne peux donc pas simplement utiliser cmd = ssh user@remotehost. Je me demande s'il existe un module à utiliser?

99
fredley

Je vous renvoie à paramiko

voir cette question

ssh = paramiko.SSHClient()
ssh.connect(server, username=username, password=password)
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmd_to_execute)
151
shahjapan

Ou vous pouvez simplement utiliser commands.getstatusoutput :

   commands.getstatusoutput("ssh machine 1 'your script'")

Je l'ai utilisé abondamment et cela fonctionne très bien.

Dans Python 2.6+, utilisez subprocess.check_output .

41
powerrox

Avez-vous jeté un œil à Tissu ? Il vous permet de faire toutes sortes de choses distantes sur SSH en utilisant python.

25
supersighs

J'ai trouvé que paramiko était un peu trop bas et Fabric ne convenant pas vraiment à être utilisé comme bibliothèque. J'ai donc créé ma propre bibliothèque appelée spur qui utilise paramiko pour implémenter une interface légèrement plus agréable:

import spur

Shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
result = Shell.run(["echo", "-n", "hello"])
print result.output # prints hello

Si vous devez exécuter à l'intérieur d'un shell:

Shell.run(["sh", "-c", "echo -n hello"])
14
Michael Williamson

Tous ont déjà déclaré (recommandé) d'utiliser paramiko et je ne fais que partager un code python (API, pourrait-on dire) qui vous permettra d'exécuter plusieurs commandes à la fois.

pour exécuter des commandes sur différents nœuds, utilisez: Commands().run_cmd(Host_ip, list_of_commands)

Vous verrez un TODO, que j'ai gardé pour arrêter l'exécution si l'une des commandes échoue, je ne sais pas comment le faire. s'il vous plaît partagez vos connaissances

#!/usr/bin/python

import os
import sys
import select
import paramiko
import time


class Commands:
    def __init__(self, retry_time=0):
        self.retry_time = retry_time
        pass

    def run_cmd(self, Host_ip, cmd_list):
        i = 0
        while True:
        # print("Trying to connect to %s (%i/%i)" % (self.Host, i, self.retry_time))
        try:
            ssh = paramiko.SSHClient()
            ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
            ssh.connect(Host_ip)
            break
        except paramiko.AuthenticationException:
            print("Authentication failed when connecting to %s" % Host_ip)
            sys.exit(1)
        except:
            print("Could not SSH to %s, waiting for it to start" % Host_ip)
            i += 1
            time.sleep(2)

        # If we could not connect within time limit
        if i >= self.retry_time:
            print("Could not connect to %s. Giving up" % Host_ip)
            sys.exit(1)
        # After connection is successful
        # Send the command
        for command in cmd_list:
            # print command
            print "> " + command
            # execute commands
            stdin, stdout, stderr = ssh.exec_command(command)
            # TODO() : if an error is thrown, stop further rules and revert back changes
            # Wait for the command to terminate
            while not stdout.channel.exit_status_ready():
                # Only print data if there is data to read in the channel
                if stdout.channel.recv_ready():
                    rl, wl, xl = select.select([ stdout.channel ], [ ], [ ], 0.0)
                    if len(rl) > 0:
                        tmp = stdout.channel.recv(1024)
                        output = tmp.decode()
                        print output

        # Close SSH connection
        ssh.close()
        return

def main(args=None):
    if args is None:
        print "arguments expected"
    else:
        # args = {'<ip_address>', <list_of_commands>}
        mytest = Commands()
        mytest.run_cmd(Host_ip=args[0], cmd_list=args[1])
    return


if __== "__main__":
    main(sys.argv[1:])

Je vous remercie!

5
IAmSurajBobade

J'ai utilisé paramiko a bunch (Nice) et pxssh (aussi Nice). Je recommanderais soit. Ils fonctionnent un peu différemment mais se chevauchent relativement.

4
Eric Snow
#Reading the Host,username,password,port from Excel file
import paramiko 
import xlrd

ssh = paramiko.SSHClient()
ssh.set_missing_Host_key_policy(paramiko.AutoAddPolicy())

loc = ('/Users/harshgow/Documents/PYTHON_WORK/labcred.xlsx')
wo = xlrd.open_workbook(loc)
sheet = wo.sheet_by_index(0)
Host = sheet.cell_value(0,1)
Port = int(sheet.cell_value(3,1))
User = sheet.cell_value(1,1)
Pass = sheet.cell_value(2,1)

def details(Host,Port,User,Pass):
    ssh.connect(Host, Port, User, Pass)
    print('connected to ip ',Host)
    stdin, stdout, stderr = ssh.exec_command("")
    stdin.write('xcommand SystemUnit Boot Action: Restart\n')
    print('success')

details(Host,Port,User,Pass)
1
Harshan Gowda

Marche parfaitement...

importer paramiko

temps d'importation

ssh = paramiko.SSHClient ()

ssh.load_system_Host_keys ()

ssh.set_missing_Host_key_policy (paramiko.AutoAddPolicy ())

ssh.connect ('10 .106.104.24 ', port = 22, nom d'utilisateur =' admin ', mot de passe =' ')

temps.sommeil (5)

print ('connecté')

stdin, stdout, stderr = ssh.exec_command ("")

def execute ():

   stdin.write('xcommand SystemUnit Boot Action: Restart\n')

   print('success')

exécuter()

0
Harshan Gowda

paramiko a finalement travaillé pour moi après avoir ajouté une ligne supplémentaire, qui est vraiment importante (ligne 3):

import paramiko

p = paramiko.SSHClient()
p.set_missing_Host_key_policy(paramiko.AutoAddPolicy())   # This script doesn't work for me unless this line is added!
p.connect("server", port=22, username="username", password="password")
stdin, stdout, stderr = p.exec_command("your command")
opt = stdout.readlines()
opt = "".join(opt)
print(opt)

Assurez-vous que le paquet paramiko est installé . Source originale de la solution: Source

0
Alexander Tereshkov

Rester simple. Aucune bibliothèque requise.

import subprocess

subprocess.Popen("ssh {user}@{Host} {cmd}".format(user=user, Host=host, cmd='ls -l'), Shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
0
Ronn Macc

Regardez spurplus, un wrapper que nous avons développé autour de spur qui fournit des annotations de types et quelques astuces mineures (reconnexion de SFTP, md5 etc.): https://pypi.org/project/spurplus/

0
marko.ristin