Django3+websocket+paramiko实现远程linux shell 执行内容实时输出到web页面

本文介绍了如何使用Django3、WebSocket和Paramiko实现从Web页面远程执行Linux命令并实时显示输出。首先,通过Python的Paramiko库建立与远程Linux服务器的连接,接着配置Django的channel层和WebSocket路由,实现异步通信。在Django应用中,创建消费者端逻辑,将命令执行与视图集成。前端通过WebSocket API连接服务器,接收并显示shell执行结果。最后,调整路由和视图,确保Web页面能正确渲染并展示实时数据。
摘要由CSDN通过智能技术生成
一.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, '
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django中使用WebSocket实现系统消息通知可以通过以下步骤实现: 1. 安装Django Channels和asgiref ```bash pip install channels asgiref ``` 2. 创建一个Django应用程序 ```bash python manage.py startapp notifications ``` 3. 创建一个WebSocket路由 在`notifications`应用程序中创建一个`routing.py`文件,添加以下内容: ```python from django.urls import re_path from . import consumers websocket_urlpatterns = [ re_path(r'ws/notifications/$', consumers.NotificationConsumer.as_asgi()), ] ``` 4. 创建一个WebSocket消费者 在`notifications`应用程序中创建一个`consumers.py`文件,添加以下内容: ```python import asyncio import json from channels.consumer import AsyncConsumer from channels.db import database_sync_to_async from django.contrib.auth.models import User class NotificationConsumer(AsyncConsumer): async def websocket_connect(self, event): await self.send({ "type": "websocket.accept" }) user = self.scope["user"] if user.is_authenticated: await self.channel_layer.group_add( f"user_{user.id}", self.channel_name ) async def websocket_receive(self, event): user = self.scope["user"] if user.is_authenticated: data = json.loads(event["text"]) message = data["message"] await self.create_message(user, message) await self.channel_layer.group_send( f"user_{user.id}", { "type": "user.message", "message": message } ) async def websocket_disconnect(self, event): user = self.scope["user"] if user.is_authenticated: await self.channel_layer.group_discard( f"user_{user.id}", self.channel_name ) @database_sync_to_async def create_message(self, user, message): user = User.objects.get(id=user.id) user.notifications.create(message=message) ``` 5. 配置WebSocket路由 在`settings.py`文件中添加以下内容: ```python ASGI_APPLICATION = 'project_name.routing.application' CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer" } } ROOT_URLCONF = 'project_name.urls' INSTALLED_APPS = [ ... 'channels', 'notifications', ] ``` 6. 创建一个JavaScript文件 在`static/js/notifications.js`文件中添加以下内容: ```javascript var socket = new WebSocket("ws://" + window.location.host + "/ws/notifications/"); socket.onmessage = function(event) { var message = JSON.parse(event.data)["message"]; alert(message); } ``` 7. 在模板中引入JavaScript文件 在需要使用WebSocket的模板中添加以下内容: ```html {% load static %} <script src="{% static 'js/notifications.js' %}"></script> ``` 现在,当用户登录并连接WebSocket时,他们将加入名为`user_<user_id>`的组。当用户收到新消息时,消息将保存到数据库中,并通过WebSocket发送到所有连接到该组的用户。在前端,我们使用JavaScript来处理接收到的消息,这里简单地使用了一个警报框来显示消息,你可以改为使用其他的UI库。 希望这个教程能够帮助你实现DjangoWebSocket的消息通知功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值