如何在子进程中使用 ssh 密钥

How to use sshkey with subprocess

我正在尝试通过 ssh 连接到路由器并向 shell 写入命令。 我认为连接有效,因为我得到一个空输出而不是错误消息。我知道我必须使用密钥文件才能真正连接到设备。也许这就是输出为空的原因。

这是我的代码:

mykey = os.path.expanduser('C:\Users\taaiaal1\PycharmProjects\hal_dmms_application\dev_ssh')
command = 'pcb_cli -u cwmpd pcb://ipc:[/var/run/IGD] -i \'?\''

ssh = subprocess.Popen(["ssh", username + '@' + host + ':' + port, command],
                       shell=True,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE)
result = ssh.stdout.readlines()
print(result)

我应该在哪里集成密钥文件?

我想检查每一页 google 让我找到,甚至在子进程 python 文档中我也找不到任何东西。这可能吗?我正在使用 Python 3.

使用 -i 标志指定标识文件。见 ssh manual under identity_file

在你的例子中,那将是

ssh = subprocess.Popen(["ssh","-i "+mykey, username + '@' + host + ':' + port, command],
                   shell=True,
                   stdout=subprocess.PIPE,
                   stderr=subprocess.PIPE)

还有高级 SSH 库可用于 Python。

尝试:

ssh = subprocess.Popen(["ssh", "-i", "/path/to/key", username + '@' + host + ':' + port, command],
                       shell=True,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE)

Popen 需要一个以特定方式格式化的参数数组。 获得正确 arg table 的最简单方法是这样做:

command = "ssh -i my.key user@host"
args = command.split(' ')
ssh = subprocess.Popen(args)

一些建议:

  • 首先port不是在:之后给出的,它是用-p选项给出的

  • 如果需要密钥,则必须使用 -i 选项指定它。确保密钥的权限为 0400.

  • 您将远程命令作为列表给出,并且还给出 shell=True 这些在某种程度上是互斥的选项。如果你想使用 shell=True 那么你将命令作为单个字符串给出。

  • 如果想收集远程命令的输出,只需使用subprocess.check_output。它在内部使用 popen() 函数,但为您提供了更简单的界面。不要忘记函数周围的 try/except,因为如果 ssh 本身出现问题或远程命令的退出状态为非零,它会引发异常。

您的代码可能如下所示:

try:
    out = subprocess.check_output(["ssh", "-i", "<path to your key>", "-p", "<port number>", "{}@{}".format(user, host), command])
    print(out)
except CalledProcessError as e:
    pass

如果您想了解执行远程命令的一些良好做法,请查看我的 implementation 执行远程命令。

PS: 使用子进程函数有两种不同的方式:一种需要 shell 来执行您的命令,例如,如果远程命令有通配符 (ls *.txt) 或您的远程命令不需要 shell 来执行 uname -a。请查看上面的子流程文档 link。