使用Python进行SSH的最简单方法是什么?


82

如何简单地从本地Python(3.0)脚本SSH到远程服务器,提供登录名/密码,执行命令并将输出打印到Python控制台?

我宁愿不使用任何大型外部库或在远程服务器上安装任何东西。

Answers:


42

我还没有尝试过,但是这个pysftp模块可能会有所帮助,而后者又使用了paramiko。我相信一切都在客户端。

有趣的命令可能是.execute()在远程计算机上执行任意命令。(该模块的功能.get().put方法也更多地暗示了它的FTP特性)。

更新:

在我最初链接到的博客文章不再可用之后,我重新编写了答案。现在,一些引用此答案的旧版本的评论看起来很奇怪。


好发现!只要您不关心自定义错误响应,此附加抽象将非常有用。
卡斯卡贝尔

ssh模块可以达到目的。简单,工作正常。无需通过Paramiko API搜索。
Christopher Tokar,2009年

2
您提供的链接中指向ssh.py文件的链接已损坏:/
dgorissen 2011年

是的,请给我们一个新链接。我在github上找到了ssh.py,但是不一样(也不是很好)
joedborg 2011年

1
pysftp软件包仅提供SFTP。远离SSH客户端。
bortzmeyer

61

您可以按照上面的建议使用Paramiko自己编写代码。另外,您可以查看Fabric,这是一个python应用程序,用于完成您所要求的所有事情:

Fabric是一个Python库和命令行工具,旨在通过SSH协议简化部署应用程序或执行系统管理任务。它提供了用于运行任意Shell命令(以普通登录用户身份或通过sudo),上传和下载文件等工具。

我认为这符合您的需求。尽管它确实依赖于需要在客户端上安装的paramiko和pycrypt,但它也不是一个很大的库,不需要安装服务器。

该应用程序曾经在这里。现在可以在这里找到。

* The official, canonical repository is git.fabfile.org
* The official Github mirror is GitHub/bitprophet/fabric

有几篇很好的文章,尽管您应该小心,因为它在过去六个月中发生了变化:

使用Fabric部署Django

现代Python黑客的工具:Virtualenv,Fabric和Pip

使用Fabric和Virtualenv轻松进行部署


以后:Fabric不再需要paramiko来安装:

$ pip install fabric
Downloading/unpacking fabric
  Downloading Fabric-1.4.2.tar.gz (182Kb): 182Kb downloaded
  Running setup.py egg_info for package fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no files found matching 'fabfile.py'
Downloading/unpacking ssh>=1.7.14 (from fabric)
  Downloading ssh-1.7.14.tar.gz (794Kb): 794Kb downloaded
  Running setup.py egg_info for package ssh
Downloading/unpacking pycrypto>=2.1,!=2.4 (from ssh>=1.7.14->fabric)
  Downloading pycrypto-2.6.tar.gz (443Kb): 443Kb downloaded
  Running setup.py egg_info for package pycrypto
Installing collected packages: fabric, ssh, pycrypto
  Running setup.py install for fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no files found matching 'fabfile.py'
    Installing fab script to /home/hbrown/.virtualenvs/fabric-test/bin
  Running setup.py install for ssh
  Running setup.py install for pycrypto
...
Successfully installed fabric ssh pycrypto
Cleaning up...

但是,这主要是修饰性的:ssh是paramiko的分支,两个库的维护者是相同的(Jeff Forcier,也是Fabric的作者),并且维护者计划以paramiko的名称重新组合paramiko和ssh。(通过pbanka进行此更正。)


因为这似乎是一个有趣的链接,所以我想对其进行更新,因为您现在已损坏。请使用:clemesha.org/blog/...
dlewin

询问者是否未指定他不想使用“大型外部库”?当作者真正要求的只是简单的一次性ssh配方时,Paramiko和Fabric都是过大的。
Zoran Pavlovic 2012年

1
@Zoran Pavlovic:所有答案都是安装本地软件包(paramiko,fabric,ssh,libssh2)或使用子进程运行ssh。后者是一个无需安装的解决方案,但是我认为生成ssh不是一个好主意,并且OP也没有,因为他选择了安装ssh模块的答案。这些文档说:“ ssh.py提供了三种常见的SSH操作,即获取,放置和执行。它是对Paramiko的高级抽象。” 因此,除非您偏爱编码繁重的libssh2,否则没有一致的建议。我倾向于在无法合理满足OP条件的情况下提供良好的解决方案。
hughdbrown 2012年

24

如果要避免任何其他模块,可以使用子流程模块来运行

ssh [host] [command]

并捕获输出。

尝试类似的方法:

process = subprocess.Popen("ssh example.com ls", shell=True,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output,stderr = process.communicate()
status = process.poll()
print output

要处理用户名和密码,可以使用子进程与ssh进程进行交互,或者可以在服务器上安装公钥以避免出现密码提示。


7
但是,如果客户端在Windows上该怎么办?
内森

ssh通过管道为子进程提供密码可能很困难。请参阅为什么不只使用管道(popen())?。您可能需要ptypexpect模块要解决它。
jfs

似乎不适用于字符串'ssh somecomputer; python -c“ import numpy; print numpy .__ version__”'说它不知道命令“ import”
usethedeathstar 2014年

1
@usethedeathstar:将整个远程命令用引号引起来:ssh somecomputer'python -c“ import this; print this”'
Neil

17

我已经为libssh2编写了Python绑定。Libssh2是实现SSH2协议的客户端库。

import socket
import libssh2

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('exmaple.com', 22))

session = libssh2.Session()
session.startup(sock)
session.userauth_password('john', '******')

channel = session.channel()
channel.execute('ls -l')

print channel.read(1024)

2
看来很底层。例如(您自己的示例),您必须明确声明使用IPv4或IPv6(与OpenSSH命令行客户端无关)。另外,我也找不到如何使其与ssh-agent一起使用。
bortzmeyer

2
pylibssh2的优点在于,它比paramiko等ssh的任何本机python实现都更快地传输文件。
Damien

8

您对“最简单的”的定义在这里很重要-简单的代码意味着使用模块(尽管“大的外部库”是夸大的)。

我相信最新(积极开发)的模块是paramiko。它包含下载中的演示脚本,并具有详细的在线API文档。您也可以尝试pxpect中包含的PxSSH。第一个链接中有一个简短的示例以及文档。

再次强调简单性,请注意,良好的错误检测将始终使您的代码看起来更复杂,但是您应该能够重用示例脚本中的许多代码,然后将其忽略。


6

像hughdbrown,我喜欢Fabric。请注意,虽然它实现了自己的声明式脚本(用于进行部署等),但也可以将其作为Python模块导入并在您的程序中使用,而无需编写Fabric脚本。

Fabric具有新的维护程序,并且正在被重写;这意味着您(当前)在网络上找到的大多数教程都不适用于当前版本。此外,Google仍将旧的“结构”页面显示为第一个结果。

有关最新文档,您可以查看:http : //docs.fabfile.org


Fabric对所有ssh东西都使用了paramiko pypi.python.org/pypi/ssh的fork 。
达米安

6

我发现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

您还可以选择在程序运行时打印其输出,如果要在退出之前查看长时间运行的命令的输出,这将很有用:

result = shell.run(["echo", "-n", "hello"], stdout=sys.stdout)

不支持运行非标准命令,例如在某些路由器(MikroTik)上以“ /”作为前缀的命令,此库会引发错误。对于标准的Linux主机,它似乎还不错。
巴本·瓦尔丹扬

当我将IP地址传递给主机名时,它会引发一个错误,指出在known_hosts中找不到IP ...
rexbelia

@rexbelia这是SSH的正常行为:为了确保您正在与正确的服务器通信,SSH只会接受来自主机的密钥(如果已知)。解决方案是将相关密钥添加到known_hosts,或将missing_host_key参数设置为适当的值,如文档中所述。
Michael Williamson

4

为了那些到达这里的人的利益,谷歌搜索python ssh示例。原来的问题和答案现在几乎已经破译了。看起来paramiko已经获得了一些功能(好吧,我承认-这里只是猜测-我是Python的新手),您可以直接使用paramiko创建ssh客户端。

import base64
import paramiko

client = paramiko.SSHClient()

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.1.1', username='user', password='password')
stdin, stdout, stderr = client.exec_command('cat /proc/meminfo')
for line in stdout:
    print('... ' + line.strip('\n'))
client.close()

这段代码改编自https://github.com/paramiko/paramiko的演示, 对我有用。


1

这对我有用

import subprocess
import sys
HOST="IP"
COMMAND="ifconfig"

def passwordless_ssh(HOST):
        ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],
                       shell=False,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE)
        result = ssh.stdout.readlines()
        if result == []:
                error = ssh.stderr.readlines()
                print >>sys.stderr, "ERROR: %s" % error
                return "error"
        else:
                return result

1

please refer to paramiko.org, its very useful while doing ssh using python.

import paramiko

import time

ssh = paramiko.SSHClient() #SSHClient() is the paramiko object</n>

#Below lines adds the server key automatically to know_hosts file.use anyone one of the below

ssh.load_system_host_keys() 

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:

#Here we are actually connecting to the server.

ssh.connect('10.106.104.24', port=22, username='admin', password='')

time.sleep(5)

#I have mentioned time because some servers or endpoint prints there own information after 
#loggin in e.g. the version, model and uptime information, so its better to give some time 
#before executing the command.

#Here we execute the command, stdin for input, stdout for output, stderr for error

stdin, stdout, stderr = ssh.exec_command('xstatus Time')

#Here we are reading the lines from output.

output = stdout.readlines() 

print(output)


#Below all are the Exception handled by paramiko while ssh. Refer to paramiko.org for more information about exception.


except (BadHostKeyException, AuthenticationException,  
    SSHException, socket.error) as e:           

print(e)

0

看看spurplus是我们开发用来管理远程计算机和执行文件操作的spurparamiko的包装。

Spurplus提供了一个现成的check_output()功能:

import spurplus
with spurplus.connect_with_retries(
        hostname='some-machine.example.com', username='devop') as shell:
     out = shell.check_output(['/path/to/the/command', '--some_argument']) 
     print(out)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.