使用Python在ssh上执行命令

Perform commands over ssh with Python

我正在编写一个脚本来自动执行Python中的一些命令行命令。现在我这样打电话:

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

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


我把你介绍给帕拉米科

看到这个问题

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


或者您只需使用commands.getstatusoutput:

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

我用得很广泛,效果很好。

在python 2.6+中,使用subprocess.check_output


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


我发现Paramiko有点太低级了,而且Fabric也不太适合用作库,所以我把自己的名为spur的库放在一起,它使用Paramiko来实现一个更好的接口:

1
2
3
4
5
import spur

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

如果需要在shell中运行:

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


所有人都已经声明(推荐)使用paramiko,我只是共享一个允许您一次执行多个命令的python代码(比如api)。

要在不同的节点上执行命令,请使用: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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/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:])

谢谢您!


我用了一堆帕拉米科(不错)和pxssh(也不错)。我也推荐。它们的工作方式稍有不同,但在使用上有较大的重叠。


帕拉米科在加了一行后终于为我工作了,这是非常重要的一行(第3行):

1
2
3
4
5
6
7
8
9
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)

确保安装了Paramiko软件包。解决方案的原始来源:来源


请看一下spurplus,这是我们围绕spur开发的一个包装器,它提供了类型注释和一些小技巧(重新连接sftp、md5等):https://pypi.org/project/spurplus/