paramiko

paramiko是ssh服务最经常使用的模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。

paramiko实现ssh2不外乎两个角度:SSH客户端与服务端

  • SSHClient:包装了Channel,Transport,SFTPClient。
  • Channel:是一种Socket类,一种安全的SSH传输通道。
  • Transport:是一种加密的会话(但是这样一个对象的Session并未建立),并且创建了一个加密的tunnels,这个tunnels叫做Channel。
  • Session:是Client与Server保持连接的对象,用Connect(),start_client(),start_server()开始会话。

具体请参考paramiko的库文档:http://docs.paramiko.org/en/2.0/index.html

使用pip install paramiko安装,失败的话,建议使用yum安装:yum install python-paramiko

代码实例:

paramiko远程密码连接:

import paramiko  

#实例化SSHClient
client = paramiko.SSHClient() #创建ssh连接日志文件(只保留前一次连接的详细日志,以前的日志会自动被覆盖)
paramiko.util.log_to_file('paramiko.log') #自动添加策略,保存服务器的主机名和密钥信息,如果不添加,不在know_hosts文件中记录的主机将无法连接
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接SSH服务端,以用户名和密码进行认证
client.connect(hostname='127.0.0.1', port=, username='root', password='') #打开一个Channel并执行命令
stdin,stdout,stderr = client.exec_command(command) #打印执行结果
result=stdout.read().decode('utf-8')
print(result) #关闭SSHClient连接
client.close()

SSHClient()里面有一个transport变量,这个是用于获取连接的,因此我们也可以单独获取到transport变量,然后执行连接操作:

import paramiko

#创建一个通道
transport = paramiko.Transport(('127.0.0.1', )) #用户名密码连接服务器
transport.connect(username='root', password='') #实例化SSHClient
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command(command)
print(stdout.read().decode('utf-8')) #关闭连接
transport.close()

paramiko使用密钥连接

import paramiko

# 配置私人密钥文件位置
private = paramiko.RSAKey.from_private_key_file('/Users/zjz/.ssh/id_rsa')

#实例化SSHClient
client = paramiko.SSHClient()

#自动添加策略,保存服务器的主机名和密钥信息,如果不添加,那么不再本地know_hosts文件中记录的主机将无法连接
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

#连接SSH服务端,以用户名和密码进行认证
client.connect(hostname='127.0.0.1',port=,username='root',pkey=private)

# 打开一个Channel并执行命令
stdin, stdout, stderr = client.exec_command(command)
# stdout 为正确输出,stderr为错误输出,同时是有1个变量有值

# 打印执行结果
print(stdout.read().decode('utf-8'))

# 关闭SSHClient
client.close()

使用transport封装使用密钥连接:

import paramiko

# 配置私人密钥文件位置
private = paramiko.RSAKey.from_private_key_file('/Users/zjz/.ssh/id_rsa')

# 创建一个通道
transport = paramiko.Transport(('127.0.0.1', ))
transport.connect(username='root', pkey=private_key)

#实例化SSHClient
client = paramiko.SSHClient()
client._transport = transport

# 打开一个Channel并执行命令
stdin, stdout, stderr = client.exec_command('df -h ')
# stdout 为正确输出,stderr为错误输出,同时是有1个变量有值

# 打印执行结果
print(stdout.read().decode('utf-8'))

# 关闭SSHClient
transport.close()

SFTPClient实现上传文件

import paramiko

# 获取Transport实例
tran = paramiko.Transport(('127.0.0.1', ))
# 连接SSH服务端,使用password
tran.connect(username="root", password='')

# 或使用
# 配置私人密钥文件位置
private = paramiko.RSAKey.from_private_key_file('/Users/zjz/.ssh/id_rsa')

# 连接SSH服务端,使用pkey指定私钥
tran.connect(username="root", pkey=private)

# 获取SFTP实例
sftp = paramiko.SFTPClient.from_transport(tran)

# 设置上传的本地/远程文件路径
localpath = "/Users/1.txt"
remotepath = "/tmp/1.txt"

# 执行上传动作
sftp.put(localpath, remotepath)

#如果远程主机有这个文件则返回一个对象,负责抛出异常
try:
sftp.file(remotepath)
print("上传成功")
except IOError:
print("上传失败")
finally:

# 关闭连接
tran.close()

SFTPClinet实现下载文件

import paramiko
import os

# 获取Transport实例
tran = paramiko.Transport(('127.0.0.1', ))

# 连接SSH服务端,使用password
tran.connect(username="root", password='')

# 或使用
# 配置私人密钥文件位置
private = paramiko.RSAKey.from_private_key_file('/Users/zjz/.ssh/id_rsa')

# 连接SSH服务端,使用pkey指定私钥
tran.connect(username="root", pkey=private)

# 获取SFTP实例
sftp = paramiko.SFTPClient.from_transport(tran)

# 设置下载的本地/远程文件路径
localpath = "/Users/1.txt"
remotepath = "/tmp/1.txt"

#判断远程服务器是否有这个文件
try:
sftp.file(remotepath)
#执行下载动作
sftp.get(remotepath, localpath)
except IOError as e:
print(remotepath+"remote file no exit!")
exit()
finally:
#关闭连接
sftp.close()
if os.path.isfile(localpath):
print("下载成功")
else:
print("下载失败")

SSHClient也可以实现交互式终端

核心代码:

# 打开一个通道
channel = trans.open_session()

# 获取终端
channel.get_pty()

# 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
channel.invoke_shell()

重要的是select模块的使用,select会监听socket或者文件描述符的I/O状态变化,并返回变化的socket或者文件描述符的对象

r_list,w_list,x_list = select.select(rlist, wlist, xlist, timeout])

参数详解:

  • rlist:list类型,监听其中的socket或者文件描述符是否变为可读状态,返回那些可读的socket或者文件描述符组成的list。
  • wlist:list类型,监听其中的socket或者文件描述符是否变为可写状态,返回那些可写的socket或者文件描述符组成的list。
  • xlist:list类型,监听其中的socket或者文件描述符是否出错,返回那些出错的socket或者文件描述符组成的list。
  • timeout:设置select的超时时间,设置为None代表永远不会超时,即阻塞。

详细模块用法见:https://blog.csdn.net/weixin_43367828/article/details/84640103

xshell功能实现

import paramiko 
import os
import select
import sys # 建立一个socket
trans = paramiko.Transport(('127.0.0.1', )) # 启动一个客户端
trans.start_client() # 如果使用rsa密钥登录的话
'''
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='root', password='123456') # 打开一个通道
channel = trans.open_session() # 获取终端
channel.get_pty() # 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
channel.invoke_shell() # 下面就可以执行你所有的操作,用select实现
# 对输入终端sys.stdin和 通道进行监控,
# 当用户在终端输入命令后,将命令交给channel通道,这个时候sys.stdin就发生变化,select就可以感知
# channel的发送命令、获取结果过程其实就是一个socket的发送和接受信息的过程 while True:
readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
# 如果是用户输入命令了,sys.stdin发生变化
if sys.stdin in readlist:
# 获取输入的内容
input_cmd = sys.stdin.read(1)
# 将命令发送给服务器
channel.sendall(input_cmd)
# 服务器返回了结果,channel通道接受到结果,发生变化 select感知到
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()

SSHClient实现堡垒机模式下的命令执行

堡垒机在一定程度上提升了运营安全级别,但同时也提高了日常运营成本,作为管理的中转设备,任何针对业务服务器的管理请求都会经过此节点,比如SSH协议,首先运维人员在办公电脑通过SSH协议登陆堡垒机,再通过堡垒机SSH跳转到所有的业务服务器进行维护操作。

可以利用paramiko的invoke_shell机制实现通过堡垒机实现服务器操作,原理是SSHClient.connect到堡垒机后开启一个新的SSH会话(session),通过新的会话运行 "sshuser@IP" 去实现远程命令执行。

SFTPClient实现堡垒机模式下的远程文件上传

实现堡垒机模式下的文件上传,原理是通过paramiko的SFTPClient将文件从办公设备上传至堡垒机指定的临时目录,如 /tmp。再通过SSHClient的invoke_shell方法开启ssh会话,执行scp命令,将 /tmp下的指定文件复制到目标业务服务器上。

具体代码实现请参考:http://www.cnblogs.com/charliedaifu/p/10098848.html

sftp是安全文件传输协议,提供一种安全的加密方法,sftp是SSH的一部分,SFTPClient类实现了sftp客户端,通过已建立的SSH通道传输文件,与其他的操作,如下:

方法 描述
sftp.getcwd() 返回当前工作目录
sftp.chdir(path) 改变工作目录
sftp.chmod(path, mode) 修改权限
sftp.chown(path, uid, gid) 设置属主属组
sftp.close() 关闭sftp
sftp.file(filename, mode=’r’, bufsize=-1) 读取文件
sftp.from_transport(s) 创建SFTP客户端通道
sftp.listdir(path=’.’) 列出目录,返回一个列表
sftp.listdir_attr(path=’.’) 列出目录,返回一个SFTPAttributes列表
sftp.mkdir(path, mode=511) 创建目录
sftp.normalize(path) 返回规范化path
sftp.open(filename, mode=’r’, bufsize=-1) 在远程服务器打开文件
sftp.put(localpath, remotepath, callback=None) localpath文件上传到远程服务器remotepath
sftp.get(remotepath, localpath, callback=None) 从远程服务器remotepath拉文件到本地localpath
sftp.readlink(path) 返回一个符号链接目标
sftp.remove(path) 删除文件
sftp.rename(oldpath, newpath) 重命名文件或目录
sftp.rmdir(path) 删除目录
sftp.stat(path) 返回远程服务器文件信息(返回一个对象的属性)
sftp.truncate(path, size) 截取文件大小
sftp.symlink(source, dest) 创建一个软链接(快捷方式)
sftp.unlink(path) 删除软链接

参考连接:

https://blog.csdn.net/songfreeman/article/details/50920767

https://blog.csdn.net/qq_29778641/article/details/82186438

https://blog.csdn.net/forever_wen/article/details/82556154

最新文章

  1. Scala相关
  2. 关于git新建本地分支与远程分支关联问题
  3. Android 读写SD卡的文件
  4. javascript中 IE事件处理程序中try catch用法
  5. zynq 之u-boot
  6. ibatis报错
  7. JAVA Socket地址绑定
  8. Sql server 事务 存储过程
  9. 给Ubuntu安装KDE桌面 [转]
  10. Python - 字母算术谜题
  11. jQuery 学习总结(上)
  12. LINQ学习系列-----2.1 一个Linq语句
  13. protobuf的下载、编译和使用
  14. mybatis 模糊查询 like的三种方式
  15. vue+axios如何操作数据交互
  16. Error in building opencv with ffmpeg
  17. [剑指Offer]59-队列的最大值(题目二待补)
  18. php返回上一页
  19. Linux 常用命令标记
  20. hadoop mongodb install(3)

热门文章

  1. 理解javascript中的with关键字
  2. Yii登录验证和全局访问用户ID
  3. 《笔者带你剖析Apache Commons DbUtils 1.6》(转)
  4. subline自定义快捷键
  5. dx工具(android将jar包转成dex格式二进制jar包工具)
  6. Android Theme的使用
  7. 有关Botton的用法(二)
  8. Xdebug日志文件不显示
  9. 给安卓端调用的短信发送接口demo
  10. php命令执行