、简介
paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。
由于使用的是python这样的能够跨平台运行的语言,所以所有python支持的平台,如Linux, Solaris, BSD, MacOS X, Windows等,paramiko都可以支持,因此,如果需要使用SSH从一个平台连接到另外一个平台,进行一系列的操作时,paramiko是最佳工具之一。
二:安装
安装paramiko有两个先决条件,python和另外一个名为PyCrypto的模块。
通常安装标准的python模块,只需要在模块的根目录下运行:
python setup.py build
python setup.py install
以上两条命令即可,paramiko和PyCrypto也不例外,唯一麻烦的就是安装PyCrypto时,需要GCC库编译,如果没有GCC库会报错,会导致PyCrypto以及paramiko无法安装。
以下以32 位的windows XP为例,说明paramiko的安装过程
1:安装python,2.2以上版本都可以,我使用的是2.5,安装过程略,并假设安装目录是c:\python。
2:判断本地是否安装了GCC,并在PATH变量可以找到,如果没有,可使用windows 版的GCC,即MinGW,下载地址:http://sourceforge.net/projects/mingw/,然后运行下载后的exe文件进行网络安装,假设目录为C:\mingw,在PATH中加入 C:\mingw\bin,并在c:\python\lib\distutils下新建一个名称是distutils.cfg的文件,填入:
3:下载PyCrypto ,地址是
https://www.dlitz.net/software/pycrypto/
安装PyCrypto:
C:\python\python.exe setup.py build
C:\python\python.exe setup.py install
运行python.exe,在提示符下输入:
如果没有出现错误提示,说明Crypto安装成功
easy_install fabric 安装到pycrypto 出现 Unable to find vcvarsall.bat 的错误 google 之,安装MinGW, 在python的Lib\distutils目录下,找到distutils.cfg文件(如果没有,就创建一个)。加上下面内容:
[build] compiler=mingw32然后到pycrypto目录下执行 python setup.py build --compiler=mingw32
我的没有,创建了一个。但是又发现出现RuntimeError: chmod error,可能是win下面没有这个命令吧,
google搜了下,原来要装msys,然后重新安装MinGW,选上msys,再次执行
python setup.py build --compiler=mingw32,
又出现
cc1.exe: 错误:unrecognized command line option ‘-mno-cygwin’,看意思,应该是gcc 不识别-mno-cygbin的命令,
google搜了下,意思差不多,然后找到Lib\distutils\cygwinccompiler,然后把里面的-mno-cygbin全部删除。
再次执行python setup.py build --compiler=mingw32,终于通过了。
最后再执行easy_install fabric,顺利安装。 |
4:下载paramiko,地址是http://www.lag.net/paramiko/
C:\python\python.exe setup.py build
C:\python\python.exe setup.py install
运行python.exe,在提示符下输入:
如果没有出现错误提示,说明paramiko安装成功
三: 使用paramiko
如果大家感觉安装paramiko还是略有麻烦的话,当使用到paramiko提供的方便时便会觉得这是十分值得的。
下面是两种使用paramiko连接到linux服务器的代码
方式一:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("某IP地址",22,"用户名", "口令")
上面的第二行代码的作用是允许连接不在know_hosts文件中的主机。
paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能。这是一个第三方的软件包,使用之前需要安装。
1 基于用户名和密码的 sshclient 方式登录
# 建立一个sshclient对象
ssh = paramiko.SSHClient()
# 允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 调用connect方法连接服务器
ssh.connect(hostname='192.168.2.129', port=22, username='super', password='super')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df -hl')
# 结果放到stdout中,如果有错误将放到stderr中
print(stdout.read().decode())
# 关闭连接
ssh.close()
2 基于用户名和密码的 transport 方式登录
方法1是传统的连接服务器、执行命令、关闭的一个操作,有时候需要登录上服务器执行多个操作,比如执行命令、上传/下载文件,方法1则无法实现,可以通过如下方式来操作
# 实例化一个transport对象
trans = paramiko.Transport(('192.168.2.129', 22))
# 建立连接
trans.connect(username='super', password='super')
# 将sshclient的对象的transport指定为以上的trans
ssh = paramiko.SSHClient()
ssh._transport = trans
# 执行命令,和传统方法一样
stdin, stdout, stderr = ssh.exec_command('df -hl')
print(stdout.read().decode())
# 关闭连接
trans.close()
3 基于公钥密钥的 SSHClient 方式登录
# 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
# 建立连接
ssh = paramiko.SSHClient()
ssh.connect(hostname='192.168.2.129',
port=22,
username='super',
pkey=pkey)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df -hl')
# 结果放到stdout中,如果有错误将放到stderr中
print(stdout.read().decode())
# 关闭连接
ssh.close()
4 基于密钥的 Transport 方式登录
# 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
# 建立连接
trans = paramiko.Transport(('192.168.2.129', 22))
trans.connect(username='super', pkey=pkey)
# 将sshclient的对象的transport指定为以上的trans
ssh = paramiko.SSHClient()
ssh._transport = trans
# 执行命令,和传统方法一样
stdin, stdout, stderr = ssh.exec_command('df -hl')
print(stdout.read().decode())
# 关闭连接
trans.close()
##### 传文件 SFTP ###########
# 实例化一个trans对象# 实例化一个transport对象
trans = paramiko.Transport(('192.168.2.129', 22))
# 建立连接
trans.connect(username='super', password='super')
# 实例化一个 sftp对象,指定连接的通道
sftp = paramiko.SFTPClient.from_transport(trans)
# 发送文件
sftp.put(localpath='/tmp/11.txt', remotepath='/tmp/22.txt')
# 下载文件
# sftp.get(remotepath, localpath)
trans.close()
5 实现输入命令立马返回结果的功能
以上操作都是基本的连接,如果我们想实现一个类似xshell工具的功能,登录以后可以输入命令回车后就返回结果:
import paramiko
import os
import select
import sys
trans = paramiko.Transport(('192.168.2.129', 22))
trans.start_client()
'''
default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
trans.auth_publickey(username='super', key=prikey)
'''
trans.auth_password(username='super', password='super')
channel = trans.open_session()
channel.get_pty()
channel.invoke_shell()
while True:
readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
if sys.stdin in readlist:
input_cmd = sys.stdin.read(1)
channel.sendall(input_cmd)
if channel in readlist:
result = channel.recv(1024)
if len(result) == 0:
print("\r\n**** EOF **** \r\n")
break
sys.stdout.write(result.decode())
sys.stdout.flush()
channel.close()
trans.close()
- 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
6 支持tab自动补全
import paramiko
import os
import select
import sys
import tty
import termios
'''
实现一个xshell登录系统的效果,登录到系统就不断输入命令同时返回结果
支持自动补全,直接调用服务器终端
'''
trans = paramiko.Transport(('192.168.2.129', 22))
trans.start_client()
'''
default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
trans.auth_publickey(username='super', key=prikey)
'''
trans.auth_password(username='super', password='super')
channel = trans.open_session()
channel.get_pty()
channel.invoke_shell()
oldtty = termios.tcgetattr(sys.stdin)
try:
tty.setraw(sys.stdin)
channel.settimeout(0)
while True:
readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
if sys.stdin in readlist:
input_cmd = sys.stdin.read(1)
channel.sendall(input_cmd)
if channel in readlist:
result = channel.recv(1024)
if len(result) == 0:
print("\r\n**** EOF **** \r\n")
break
sys.stdout.write(result.decode())
sys.stdout.flush()
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
channel.close()
trans.close()