使用 Python 通过 ssh 执行命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3586106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:50:37  来源:igfitidea点击:

Perform commands over ssh with Python

pythonssh

提问by fredley

I'm writing a script to automate some command line commands in Python. At the moment I'm doing calls thus:

我正在编写一个脚本来自动化 Python 中的一些命令行命令。目前我正在打电话:

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

However I need to run some commands on a remote machine. Manually, I would log in using ssh and then run the commands. How would I automate this in Python? I need to log in with a (known) password to the remote machine, so I can't just use cmd = ssh user@remotehost, I'm wondering if there's a module I should be using?

但是我需要在远程机器上运行一些命令。手动,我会使用 ssh 登录,然后运行命令。我将如何在 Python 中自动执行此操作?我需要使用(已知)密码登录到远程机器,所以我不能只使用cmd = ssh user@remotehost,我想知道是否有我应该使用的模块?

采纳答案by shahjapan

I will refer you to paramiko

我会把你转paramiko

see this question

看到这个问题

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

回答by supersighs

Have you had a look at Fabric? It allows you to do all sorts of remote stuff over SSH using python.

你看过Fabric吗?它允许您使用 python 通过 SSH 执行各种远程操作。

回答by powerrox

Or you can just use commands.getstatusoutput:

或者你可以只使用commands.getstatusoutput

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

I used it extensively and it works great.

我广泛使用它,效果很好。

In Python 2.6+, use subprocess.check_output.

在 Python 2.6+ 中,使用subprocess.check_output.

回答by Eric Snow

I have used paramikoa bunch (nice) and pxssh(also nice). I would recommend either. They work a little differently but have a relatively large overlap in usage.

我已经使用了一堆paramiko(很好)和pxssh(也很好)。我会推荐。它们的工作方式略有不同,但在使用上有相对较大的重叠。

回答by Michael Williamson

I found paramiko to be a bit too low-level, and Fabric not especially well-suited to being used as a library, so I put together my own library called spurthat uses paramiko to implement a slightly nicer interface:

我发现 paramiko 有点太低级了,而且 Fabric 不太适合用作库,所以我把我自己的库放在一起,叫做spur,它使用 paramiko 来实现一个稍微好一点的接口:

import spur

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

If you need to run inside a shell:

如果您需要在 shell 中运行:

shell.run(["sh", "-c", "echo -n hello"])

回答by IAmSurajBobade

All have already stated (recommended) using paramikoand I am just sharing a python code (API one may say) that will allow you to execute multiple commands in one go.

所有人都已经声明(推荐)使用paramiko,我只是分享了一个 python 代码(有人可能会说 API),它可以让你一次性执行多个命令。

to execute commands on different node use : Commands().run_cmd(host_ip, list_of_commands)

在不同的节点上执行命令使用: Commands().run_cmd(host_ip, list_of_commands)

You will see one TODO, which I have kept to stop the execution if any of the commands fails to execute, I don't know how to do it. please share your knowledge

你会看到一个 TODO,如果有任何命令执行失败,我会一直停止执行,我不知道该怎么做。请分享您的知识

#!/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 __name__ == "__main__":
    main(sys.argv[1:])

Thank you!

谢谢!

回答by marko.ristin

Have a look at spurplus, a wrapper we developed around spurthat provides type annotations and some minor gimmicks (reconnecting SFTP, md5 etc.): https://pypi.org/project/spurplus/

看看spurplus,我们围绕spur它开发的一个包装器,它提供了类型注释和一些小噱头(重新连接 SFTP、md5):https: //pypi.org/project/spurplus/

回答by Alexander Tereshkov

paramikofinally worked for me after adding additional line, which is really important one (line 3):

添加额外的行后,paramiko终于为我工作了,这真的很重要(第 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)

Make sure that paramiko package is installed. Original source of the solution: Source

确保已安装 paramiko 包。解决方案的原始来源:Source

回答by Harshan Gowda

Works Perfectly...

完美运行...

import paramiko
import time

ssh = paramiko.SSHClient()
#ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('10.106.104.24', port=22, username='admin', password='')

time.sleep(5)
print('connected')
stdin, stdout, stderr = ssh.exec_command(" ")

def execute():
       stdin.write('xcommand SystemUnit Boot Action: Restart\n')
       print('success')

execute()

回答by Harshan Gowda

Below example, incase if you want user inputs for hostname,username,password and port no.

下面的例子,如果你想要用户输入主机名、用户名、密码和端口号。

  import paramiko

  ssh = paramiko.SSHClient()

  ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())



  def details():

  Host = input("Enter the Hostname: ")

  Port = input("Enter the Port: ")

  User = input("Enter the Username: ")

  Pass = input("Enter the Password: ")

  ssh.connect(Host, Port, User, Pass, timeout=2)

  print('connected')

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

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

  print('success')

  details()