前言
这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题
于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。
微信小程序搜索:Python面试宝典
或可关注原创个人博客:https://lienze.tech
也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习
Paramiko
Paramiko
是SSHv2
协议的Python
实现,提供客户端和服务器功能
Paramiko
本身是一个围绕SSH
网络概念的纯Python
接口
利用paramiko
我们可以通过Python
方便的进行ssh
操作
paramiko
包含两个核心组件:SSHClient
和SFTPClient
SSHClient
SSHClient
的作用类似于Linux
的ssh
命令,是对SSH
会话的封装
该类封装了传输Transport
,通道Channel
及SFTPClient
建立的方法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
命令,打开一个新通道并执行请求的命令
该函数的返回结果为一个元组,其中包含stdin
、stdout
和stderr
,也就是我们常见的标准输入,输出以及出错
一般来说,命令的结果我们将通过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
的作用类似与Linux
的sftp
命令,是对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()