一.Python中paramiko连接远程linux服务器
python中paramiko库可以执行远程linux服务器命令并接收返回结果,基于channel信道模式,channel允许用户在不同程序间进行通信,这是实现分布式实时应用的一部分如果你不想所有的message和event都经由数据库的话
此外,它还可以和工作进程结合使用来创建基本的任务队列或者卸载任务
但是channel本身是不附带任何开箱即用的channel layer的,因为每一个channel layer都依赖于不同的网络数据传输方式
channel官方推荐的是配置channel_redis,这是一个使用Redis作为传输的Django维护层
channel2.0不同于1.x,channel layer属于完全可选部分,这意味着如果不想使用的话可以设置成空字典{}或者CHANNEL_LAYER不配置即可
同时,channel layer属于纯粹的异步接口,如果想要从同步代码调用,需要使用装饰器asgiref.sync.async_to_sync
其中channel配置redis方法如下:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("redis-server-name", 6379)],
},
},
}
默认获取channel_layer的方式是调用接口:channels.layers.get_channel_layer(),如果是在consumer中调用接口的话可以直接使用self.channel_layer
同步函数
对于channel layer的方法(包括send()、group_send(),group_add()等)都属于异步方法,这意味着在调用的时候都需要使用await,而如果想要在同步代码中使用它们,就需要使用装饰器asgiref.sync.async_to_sync
from asgiref.sync import async_to_sync
async_to_sync(channel_layer.send)("channel_name", {
...})
二.Django3实现远端linux执行结果实时输出到web
整体项目目录结构如下:
2.1安装paramiko,channel模块
pip3 install paramiko==2.7.2
pip install -U channels
然后编辑 settings.py
将Channels库添加到已安装的应用程序列表中。编辑 settings.py 文件,并将channels添加到INSTALLED_APPS设置中。
INSTALLED_APPS = [
# ... 'channels', # 【channels】(第1步)pip install -U channels 安装
# ...
]
2.2 创建默认路由(主websocket路由)
为了让websocket的路由和django中urls的路由系统区分,我们在web_info_api目录下新建一个route.py模块来实现websocket的路由(其实也可以合入到urls.py,这里只是进行区分),内容如下:
from django.urls import path
from . import views
websocket_urlpatterns = [
# 前端请求websocket连接
path('ws/result/', views.SyncConsumer),
]
2.3 应用(application)转发配置(基于asgi)
通常django应用application都是基于wsgi协议的,但是为了django为了兼容原有的wsgi以及支持websocket,衍生出asgi这一拓展,在与wsgi.py的同级目录下新建routing.py模块,用来转发基于asgi的websocket的application请求处理
设置执行路由对象(指定routing)
最后,将ASGI_APPLICATION设置为指向路由对象作为根应用程序,修改 settings.py 文件,最后一行添加:
ASGI_APPLICATION = ‘websocket_project.routing.application’
就是这样!一旦启用,通道就会将自己集成到Django中,并控制runserver命令。
2.4 启用信道层channel
启动channel layer
信道层是一种通信系统。它允许多个消费者实例彼此交谈,以及与Django的其他部分交谈。
通道层提供以下抽象:
通道是一个可以将邮件发送到的邮箱。每个频道都有一个名称。任何拥有频道名称的人都可以向频道发送消息。
一组是一组相关的通道。一个组有一个名称。任何具有组名称的人都可以按名称向组添加/删除频道,并向组中的所有频道发送消息。无法枚举特定组中的通道。
每个使用者实例都有一个自动生成的唯一通道名,因此可以通过通道层进行通信。
这里为了方便部署,直接使用内存作为后备存储的通道层。有条件的话,可以使用redis存储
配置CHANNEL_LAYERS
修改 settings.py 最后一行增加配置
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer",
}
}
2.5 实现Channel消费者端业务逻辑(集成到视图view中)
同步消费者很方便,因为他们可以调用常规的同步I / O函数,例如那些在不编写特殊代码的情况下访问Django模型的函数。 但是,异步使用者可以提供更高级别的性能,因为他们在处理请求时不需要创建其他线程。
这里使用同步消费,因为我测试异步消费时,web页面并不能实时展示结果。只能使用同步模式才行
具体实现代码如下:
from django.shortcuts import render
import json
import paramiko
import logging
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync
# Create your views here.
def index(request):
return render(request, '