Flask 运用Xterm实现交互终端

Xterm是一个基于X Window System的终端仿真器(Terminal Emulator)。Xterm最初由MIT开发,它允许用户在X Window环境下运行文本终端程序。Xterm提供了一个图形界面终端,使用户能够在图形桌面环境中运行命令行程序。而xterm.js是一个用于在浏览器中实现终端仿真的JavaScript库。它允许在Web页面中创建交互式的终端界面,用户可以在浏览器中运行命令行程序,执行命令,并与终端进行交互。

主要特点和功能包括:

  1. 终端仿真: xterm.js通过JavaScript模拟了一个终端环境,支持常见的终端功能,包括光标移动、颜色控制、滚动等。
  2. 多平台支持: 由于是基于JavaScript实现,xterm.js可以在各种现代浏览器上运行,无论是在桌面还是移动设备上。
  3. 自定义外观: xterm.js提供了丰富的配置选项,用户可以定制终端的外观和行为,包括颜色、字体、光标样式等。
  4. 剪贴板支持: 支持从终端复制文本到剪贴板,并从剪贴板粘贴文本到终端。
  5. WebSockets和其他集成: 可以与WebSockets等通信协议集成,以便在浏览器中实现实时的终端交互。
  6. 支持Unicode和UTF-8: 能够正确显示和处理Unicode字符,支持UTF-8编码。

xterm.js通常被用于Web应用程序中,尤其是在需要提供命令行界面的场景下,如在线终端、远程服务器管理等。这使得开发者能够在浏览器中实现类似于本地终端的交互体验,而无需使用本地终端模拟器。

AJAX 实现Web交互

AJAX(Asynchronous JavaScript and XML)是一种用于在Web应用程序中实现异步数据交换的技术。它允许在不重新加载整个页面的情况下,通过在后台与服务器进行小规模的数据交换,实现动态更新网页内容的目的。AJAX广泛用于创建交互性强、用户体验良好的Web应用程序,例如在加载新数据、进行表单验证、实现自动完成搜索等方面。

如下前端部分,通过使用ajax向后端提交数据,当success:function接收到数据后直接将数据动态回写到Xterm终端上,代码如下所示;

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="https://www.lyshark.com/javascript/xterm/xterm.css" /><script type="text/javascript" src="https://www.lyshark.com/javascript/xterm/xterm.js"></script><script type="text/javascript" src="https://www.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script>
</head>
<body><script type="text/javascript">var window_width = $(window).width()-200;var window_height = $(window).height()-300;var term = new Terminal({cols: Math.floor(window_width/9),rows: Math.floor(window_height/20),useStyle:false,convertEol: true,cursorBlink:false,cursorStyle:null,rendererType: "canvas",});term.open(document.getElementById('terminal'));function show(){var address = $("#address").val();var command = $("#command").val();console.log(command);$.ajax({url:"/",type:"POST",contentType:"application/json;",data: JSON.stringify({"address":address,"command":command}),success:function (res){// term.clear();term.writeln( "\x1B[1;3;33m IP地址: \x1B[0m" + res.address );term.writeln( "\x1B[1;3;34m 命令: \x1B[0m" + res.command );}});}</script><!--提交数据--><div id="terminal"></div><input type="text" id="address" placeholder="主机地址"/><input type="text" id="command" placeholder="执行命令"/><input type="button" value="执行命令" onclick="show()"></div>
</body>
</html>

后端部分的实现很简单,首先封装一个ssh_shell用于执行命令,用户传入数据后,直接执行并将返回结果放入到ref内即可。

from flask import Flask,render_template,request
from flask import jsonify
import paramikoapp = Flask(__name__)ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())def ssh_shell(address,username,password,port,command):ssh.connect(address,port=port,username=username,password=password)stdin, stdout, stderr = ssh.exec_command(command)result = stdout.read()if not result:result=stderr.read()ssh.close()return result.decode()@app.route('/', methods=[ 'GET', 'POST'])
def index():if request.method == "POST":# 接收数据json_value = request.get_json()ref = ssh_shell("192.168.150.128","root","123123","22",json_value["command"])# 发送数据info = dict()info["address"] = json_value["address"]info["command"] = refreturn jsonify(info)else:return render_template("index.html")if __name__ == '__main__':app.run()

AJAX实现Web终端

继续扩展将编辑框去掉,用户输入数据后直接传入到Xterm内,Xterm里卖弄判断如果出现了回车,则像后端发送ajax数据,否则继续侦听并记下输入数据。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="https://www.lyshark.com/javascript/xterm/xterm.css" /><script type="text/javascript" src="https://www.lyshark.com/javascript/xterm/xterm.js"></script><script type="text/javascript" src="https://www.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script>
</head>
<body><div id="terminal"></div><script type="text/javascript">var window_width = $(window).width()-500;var window_height = $(window).height()-300;var term = new Terminal({cols: Math.floor(window_width/9),rows: Math.floor(window_height/20),useStyle:false,convertEol: true,cursorBlink: true,        //光标闪烁cursorStyle: "underline", //光标样式rendererType: "canvas",});term.open(document.getElementById('terminal'));term.writeln("welcome to lyshark web terminal!");term.write("[shell] # ");let input = '';term.on('key', (key, ev) => {let code = key.charCodeAt(0);console.log(code);// 如果按下回车,则发送命令,并等待输出结果if(code == 13){term.write("\r\n");$.ajax({url:"/",type:"POST",contentType:"application/json;",data: JSON.stringify({"command": input}),success:function (res){term.write(res.value);}});input ='';}// 如果是退格,则清除else if(code == 127){term.write("\b");}else{input += keyterm.write(key);}});</script>
</body>
</html>

后端收到数据后解析命令,比对命令是否存在,根据不同的命令执行不同的分支。

from flask import Flask,render_template,request
from flask import jsonifyapp = Flask(__name__)@app.route('/', methods=[ 'GET', 'POST'])
def index():if request.method == "POST":# 接收数据json_value = request.get_json()["command"]if len(json_value) != 0:# 判断使用哪一个分支splite_value = json_value.split(" ")info = dict()if splite_value[0] == "help":info["value"] = "version 1.0"info["value"] = info["value"] + "\n[shell] # "return jsonify(info)elif splite_value[0] == "GetCPU":address = splite_value[1]info["value"] = "192.168.1 CPU 10%"info["value"] = info["value"] + "\n[shell] # "return jsonify(info)else:info["value"] = "命令不存在"info["value"] = info["value"] + "\n[shell] # "return jsonify(info)else:info = dict()info["value"] = "[shell] # "return jsonify(info)else:return render_template("index.html")if __name__ == '__main__':app.run()

运行后可输出一个交互式WebShell环境,如下图所示;

WebSocket 实现终端

虽然WebSSH可以方便管理主机,但如果需要批量运维则需要开发一个可以多条消息共同推送的命令行。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="https://www.lyshark.com/javascript/xterm/xterm.css" /><script type="text/javascript" src="https://www.lyshark.com/javascript/xterm/xterm.js"></script><script type="text/javascript" src="https://www.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script><script type="text/javascript" src="https://www.lyshark.com/javascript/socket.io/socket.io.min.js"></script>
</head><body><div id="terminal"></div><script type="text/javascript" charset="UTF-8">$(document).ready(function(){namespace = '/Socket';var socket = io.connect("http://" + document.domain + ":" + location.port + namespace);var window_width = $(window).width()-500;var window_height = $(window).height()-300;var term = new Terminal({cols: Math.floor(window_width/9),rows: Math.floor(window_height/20),useStyle:false,convertEol: true,cursorBlink: true,rendererType: "canvas",});// 打开Web终端term.open(document.getElementById('terminal'));term.write("[shell] # ");let input_command = '';term.on('key', (key, ev) => {let code = key.charCodeAt(0);console.log(code);// 如果按下回车,则发送命令,并等待输出结果if(code == 13){// 发送数据到后端term.write("\r\n");socket.emit("message",{"command": input_command});input_command ='';}// 如果是退格,则清除else if(code == 127){term.write("\b");}else{input_command += keyterm.write(key);}});// 接受后台返回并输出socket.on('response', function(recv){console.log(recv.value);term.write(recv.value);});});</script>
</body>
</html>

后台接收参数,并更具不同的参数执行不同的运维函数,此处只做演示,具体功能需要自行编写。

from flask import Flask,render_template,request
from flask_socketio import SocketIOasync_mode = None
app = Flask(__name__)
app.config['SECRET_KEY'] = "lyshark"
socketio = SocketIO(app)@app.route("/")
def index():return render_template("index.html")# 出现消息后,率先执行此处
@socketio.on("message",namespace="/Socket")
def socket(message):print("接收到消息:",message['command'])command = message['command']if len(command) != 0:splite_command = command.split(" ")if splite_command[0] == "help":socketio.emit("response", {"value": "version 1.0 \n"}, namespace="/Socket")elif splite_command[0] == "Ping":if len(splite_command) == 2:index = splite_command[1]for each in range(int(index)):socketio.sleep(0.1)socketio.emit("response",{"value": str(each) + "\n"}, namespace="/Socket")socketio.emit("response", {"value": "\n[shell] # "}, namespace="/Socket")else:socketio.emit("response", {"value": "lyShell: command not found \n"}, namespace="/Socket")else:socketio.emit("response", {"value": "[shell] # "}, namespace="/Socket")# 当websocket连接成功时,自动触发connect默认方法
@socketio.on("connect",namespace="/Socket")
def connect():print("链接建立成功..")# 当websocket连接失败时,自动触发disconnect默认方法
@socketio.on("disconnect",namespace="/Socket")
def disconnect():print("链接建立失败..")if __name__ == '__main__':socketio.run(app,debug=True)

Socket版本的将会更流畅,如下图所示;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/175121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin学习——kt入门合集博客 kt里的委派模式Delegation kt里的特性

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

[SpringCloud] SpringCloud配置中心的核心原理

SpringCloud是什么时候去拉取配置中心的配置中心客户端的配置信息为什么要写在bootstrap文件中对象中注入的属性是如何动态刷新的一些开源的配置中心是如何整合SpringCloud的 文章目录 1.从SpringBoot的启动过程说起1.1 大致过程 2.准备Environment的核心操作2.1 前置操作 3.pr…

SEOAI每周资讯和Linus思考 231127

欢迎查看 Linus筋斗云SEO 的每周资讯整理&#xff0c;本周的一些要点&#xff1a; Google11月核心更新和评论更新仍然没有结束9个搜索结果页的主要变化&#xff1a;图标、品牌、粉丝数、新模块GSC已索引页面狂掉&#xff1f;Google的问题&#xff0c;已修复黑五网一期间的搜索…

强化学习中的Q学习

Q学习&#xff08;Q-Learning&#xff09;是强化学习中的一种基于值的学习方法&#xff0c;用于在有限马尔可夫决策过程&#xff08;MDP&#xff09;中学习最优的动作策略。Q学习主要用于离散状态和离散动作的问题。 以下是Q学习的基本概念和步骤&#xff1a; Q-Value&#xf…

在Spring Boot中隔离@Async异步任务的线程池

在异步任务执行的时候&#xff0c;我们知道其背后都有一个线程池来执行任务&#xff0c;但是为了控制异步任务的并发不影响到应用的正常运作&#xff0c;我们需要对线程池做好相关的配置&#xff0c;以防资源过度使用。这个时候我们就考虑将线程池进行隔离了。 那么我们为啥要…

【数据结构初阶】单链表

各位读者老爷好&#xff0c;鼠鼠我又来了哈。鼠鼠我呀现在来基于C语言实现以下单链表&#xff0c;希望对你有所帮助&#xff01; 目录 1.链表的概念及结构 2.链表的分类 3.无头单向非循环链表的实现 3.1.单链表打印 3.2.单链表尾插 3.3.单链表头插 3.4.单链表尾删 3.5…

在OpenCV中基于深度学习的边缘检测

引言 如何在OpenCV中使用基于深度学习的边缘检测&#xff0c;它比目前流行的canny边缘检测器更精确。边缘检测在许多用例中是有用的&#xff0c;如视觉显著性检测&#xff0c;目标检测&#xff0c;跟踪和运动分析&#xff0c;结构从运动&#xff0c;3D重建&#xff0c;自动驾驶…

MyBatis-Plus及多数据源入门教程

开发环境配置 JDK 1.8、Maven 3.8.8、 IDEA CE 2023.2、MySQL 8.0.34 框架介绍 MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。MyBatis 是一款非常优秀的开源…

训练 CNN 对 CIFAR-10 数据中的图像进行分类

1. 加载 CIFAR-10 数据库 import keras from keras.datasets import cifar10# 加载预先处理的训练数据和测试数据 (x_train, y_train), (x_test, y_test) cifar10.load_data() 2. 可视化前 24 个训练图像 import numpy as np import matplotlib.pyplot as plt %matplotlib …

leetcode:506. 相对名次

一、题目 函数原型&#xff1a;char** findRelativeRanks(int* score, int scoreSize, int* returnSize) 二、思路 创建一个新的数组newscore&#xff0c;将原数组数据拷贝到新数组&#xff0c;降序排序新数组。 遍历原数组&#xff0c;在新数组中找到原数组中数据在新数组中的…

优雅使用docker-compose部署Skywalking

Skywalking使用docker-compose部署 version: 3.1 services: // 部署elasetic search 用于存储获取的应用信息与日志elasticsearch:image: elasticsearch:7.13.3container_name: elasticsearchprivileged: trueenvironment:- "cluster.nameelasticsearch" #设置集群名…

算法通关村第十二关-黄金挑战字符串冲刺题

最长公共前缀 描述 : 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 题目 : LeetCode 14.最长公共前缀 : 分析 : 第一种方式&#xff0c;我们可以竖着比较&#xff0c;如图所示&#xff0c;每前进一个位置就…

【论文解读】基于生成式面部先验的真实世界盲脸修复

论文地址&#xff1a;https://arxiv.org/pdf/2101.04061.pdf 代码地址&#xff1a;https://github.com/TencentARC/GFPGAN 图片解释&#xff1a; 与最先进的面部修复方法的比较&#xff1a;HiFaceGAN [67]、DFDNet [44]、Wan 等人。[61] 和 PULSE [52] 在真实世界的低质量图像…

CocosCreator 之 Tween缓动系统的使用

版本&#xff1a; 3.4.0 语言&#xff1a; TypeScript 环境&#xff1a; Mac 简介 在CocosCreator 3.x版本后&#xff0c; Tween缓动系统代替了原有的Action动作。官方使用缓动系统的主要目的之一是用于解决离线动画无法满足需求时的动态动画问题。 简单的示例&#xff1a; …

Java—学生信息管理系统(简单、详细)

文章目录 一、主界面展示二、学生类三、系统功能方法3.1 main()方法3.2 添加学生信息3.3 删除学生信息3.4 修改学生信息3.5 查看所有学生信息 四、完整代码4.1 Student .Java4.2 StudentManger.Java 前言&#xff1a;本案例在实现时使用了Java语言中的ArrayList集合来储存数据。…

【【Linux下的Petallinux 以及其他的配置】】

Linux下的Petallinux 以及其他的配置 sudo apt-get install iproute2 gawk python3 python build-essential gcc git make net-tools libncurses5-dev tftpd zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget git-core diffstat chrpath socat xterm autoconf libtoo…

HarmonyOS 位置服务开发指南

位置服务开发概述 移动终端设备已经深入人们日常生活的方方面面&#xff0c;如查看所在城市的天气、新闻轶事、出行打车、旅行导航、运动记录。这些习以为常的活动&#xff0c;都离不开定位用户终端设备的位置。 当用户处于这些丰富的使用场景中时&#xff0c;系统的位置能力…

三丶openlayer之source和layer

1.source和layer的概念 在前面的例子中&#xff0c;已经对Source和Layer有所了解了&#xff0c;我们用天地图为底图加载出来东西&#xff0c;但是这个世界上的地图不仅仅是有天地图一种类型&#xff0c;比如Google地图&#xff0c;高德地图&#xff0c;百度地图等&#xff0c;…

针对MAC上,面对8080端口被占用怎么解决

首先输入这个命令&#xff0c;在终端&#xff0c;这个是搜查命令&#xff0c;搜查当前8080端口被谁占着 sudo lsof -i :8080 杀死当前的进程 kill -9 1821 kill -9 (上面写着的PID)

SQL注入-数据库基础/SQL语法

目录 一&#xff0c;数据库概述 1.1 数据库 1.2 了解 ACID 理论 1.3 识别数据库 二&#xff0c;SQL 语法基础 三&#xff0c;SQL语句实例 3.1 SQL基础语句 3.2 SQL高级语句 四&#xff0c;基于SQL注入理解语法/函数 4.1 语法 4.2 函数 五&#xff0c;目录数据库info…