Python运维模块之paramiko使用大全

前言

这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题

于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。

微信小程序搜索:Python面试宝典

或可关注原创个人博客:https://lienze.tech

也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习

Paramiko

ParamikoSSHv2协议的Python实现,提供客户端和服务器功能

Paramiko本身是一个围绕SSH网络概念的纯Python接口

利用paramiko我们可以通过Python方便的进行ssh操作


paramiko包含两个核心组件:SSHClientSFTPClient

SSHClient

SSHClient的作用类似于Linuxssh命令,是对SSH会话的封装

该类封装了传输Transport,通道ChannelSFTPClient建立的方法open_sftp,通常用于执行远程命令

API

  • class paramiko.client.SSHClient

创建SSH客户端实例

  • SSHClient.connect(hostname, port=22, username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False..)
# 参数解释
- hostname:连接的目标主机
- port=SSH_PORT:指定端口
- username=None:验证的用户名
- password=None:验证的用户密码
- pkey=None:私钥方式用于身份验证
- key_filename=None:一个文件名或文件列表,指定私钥文件
- timeout=None:可选的tcp连接超时时间
- allow_agent=True:是否允许连接到ssh代理,默认为True 允许
- look_for_keys=True:是否在~/.ssh中搜索私钥文件,默认为True 允许
- compress=False:是否打开压缩

通过验证连接远程服务端


  • SSHClient.exec_command(command, bufsize=-1, timeout=None, get_pty=False, environment=None)
# 参数解释
- command:要执行的命令
- bufsize:与Python中文件对象的同名函数解释相同,缓冲区大小
- timeout:设置命令的超时相应事件
- get_pty:从服务器请求一个伪终端(默认为假)
- environment:一个当前shell环境的字典,远程命令的默认执行环境

command参数为要执行的shell命令,打开一个新通道并执行请求的命令

该函数的返回结果为一个元组,其中包含stdinstdoutstderr,也就是我们常见的标准输入,输出以及出错

一般来说,命令的结果我们将通过stdout进行获取


  • SSHClient.close()

关闭SSH连接


  • SSHClient.invoke_shell(term=’vt100’, width=80, height=24, width_pixels=0, height_pixels=0, environment=None)
# 参数解释
- term:模拟终端类型
- width:终端长度
- height:终端宽度
- width_pixels:终端的像素宽度
- height_pixels:终端的像素高度
- environment:命令的shell环境

ssh服务器上启动交互式shell会话

一个新的通道被打开并连接到,使用请求的终端类型和大小的伪终端,并作为返回值

换句通俗的话来讲,就是创建了一个实际的shell窗口空间进行命令交互


  • SSHClient.set_missing_host_key_policy(policy)

设置连接到没有已知主机密钥的服务器时要使用的策略

常见使用策略为paramiko.client.AutoAddPolicy,其意义为自动将主机名和新主机密钥添加到本地主机密钥对象并保存

实例代码

以下是一个简单的通过SSHClient建立的通道进行命令的传输与返回结果的获取的代码!

import paramiko 

def connect(hostname,username,password):
	client = paramiko.SSHClient() 
    # 初始化
	client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # 设置密钥策略
	client.connect(hostname,username=username,password=password)
    # 连接主机
	return client

def exec_cmd(client,cmd):
	stdin,stdout,stderr = client.exec_command(cmd)
	return stdout.read().decode(),stderr.read().decode()
def main():
	hostname = '192.168.0.104'
	username = 'pi'
	password = '123456'
	cmd = 'ps -aux'

	client = connect(hostname,username,password)
	res = exec_cmd(client, cmd)
	if res[0]:
		print(res[0])
	if res[1]:
		print('[E]:\n',res[1])
	client.close()
if __name__ == '__main__':
	main()

上面的代码通过默认建立好的连接对象进行命令的传输以及返回结果的获取

invoke_shell

  • 接下来使用invoke_shell进行虚拟终端的连接,首先初始化SSH通道
class SSHChannle:
    def __init__(self, host, username, password, port=22):
        '''
            初始化SSH通道
        '''
        self.sh = paramiko.SSHClient()
        self.sh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.sh.connect(host, username=username, password=password)
        self.channle = self.sh.invoke_shell()
  • 思路为开启两个线程,分别负责命令的接收与命令的发送
def get_ssh_recv(self):
    '''
        接收SSH通道中发来的消息
    '''
    while not self.channle.exit_status_ready():
        # 如果远程进程已退出并返回退出状态,则返回true
        time.sleep(0.1)
        try:
            buf = self.channle.recv(1024).decode('utf-8')
            print(buf,end='')
            sys.stdout.flush()
        except Exception as ex:
            print(ex)
def send_ssh_cmd(self):
    '''
        发送命令给SSH通道
    '''
    while not self.channle.exit_status_ready():
        cmd = input()
        try:
            self.channle.send(cmd + '\r')
        except Exception as ex:
            print(ex)
        sys.stdin.flush()
  • 在实例中定义run函数用来开启两个线程并负责线程的资源回收以及SSH通道的关闭
def run(self):
    ssh_recv_thread = threading.Thread(target=self.get_ssh_recv)
    ssh_send_thread = threading.Thread(target=self.send_ssh_cmd)
    ssh_recv_thread.start()
    ssh_send_thread.start()

    ssh_recv_thread.join()
    ssh_send_thread.join()

    self.sh.close()  # 关闭通道
  • win下的CMD中查看效果,其中的乱码格式其实为连接后命令传输的特殊标记格式,可以在后面结合前端中类似xterm.js等插件查看到实际花里胡哨的效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A5wuYlKp-1634896751504)(/Users/lienze/Documents/Python Courseware/MD格式/静态资源/invoke_shell.gif)]

SFTPClient

SFTPClient的作用类似与Linuxsftp命令,是对SFTP客户端的封装

用以实现远程文件操作,如文件上传、下载、修改文件权限等操作

API

  • 官方文档:docs.paramiko.org/en/2.4/api/sftp.html

  • sftp=paramiko.SFTPClient.from_transport(t,window_size=None,max_packet_size=None)

# 参数解释
- t:该参数可以通过paramiko.Transport( (ip,port )),创建一个已通过验证的传输通道,参数为IP和端口的二元组

根据参数t指定的已验证传输通道进行SFTP客户端的创建

  • sftp.put(localpath, remotepath, callback=None, confirm=True)

上传本地路径为localpath的文件到目标主机remotepath

  • sftp.get(remotepath, localpath, callback=None)

下载远程路径为remotepath路径的的文件到本地主机localpath

  • open(filename, mode=’r’, bufsize=-1)

打开位于远程主机上的文件,与open函数类似,返回文件对象

  • listdir(path='.')

返回给定路径下文件及目录的列表,默认路径为当前工作目录

  • chdir(path=None)

修改当前SFTP连接会话的工作目录

  • lstat(path)

检索当前path所指向的文件信息

  • mkdir(path,mode=511)

根据path在目标主机创建默认权限为511的目录

  • rmdir(path)

删除给定path所指向的目录

  • remove(path)

删除给定path所指向的文件

实例代码

以下是一个比较简陋的关于SFTPClient的测试代码

import paramiko
def connecnt(hostname,username,password): #创建连接对象
    client = paramiko.Transport( (hostname,22))
    try:
        client.connect(username=username,password=password)
    except paramiko.SSHException:
        return None
    sftp_client = paramiko.SFTPClient.from_transport(client)
    return sftp_client

def main():
    hostname = '192.168.0.104'
    username = 'pi'
    password = '123456'
    sftp_client = connecnt(hostname,username,password)
    remotefile_path = '/home/pi/test' # 目标主机文件路径
    localfile_path = '/home/test' # 本地主机文件路径

    sftp_client.put(localfile_path, remotefile_path) #上传本地test文件到远程
    sftp_client.get(remotefile_path, localfile_path) #下载远程test文件到本地
    print(sftp_client.listdir())
    print(sftp_client.lstat(remotefile_path))
    with sftp_client.open(remotefile_path) as fp:
        print(fp.read().decode())
    #print(sftp_client.remove(remotefile_path))

if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/HeroicLee/article/details/120910856