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 paramiko app = 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"] = ref
return 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 += key
term.write(key);
}
});
</script>
</body>
</html>

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

from flask import Flask,render_template,request
from flask import jsonify app = 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 += key
term.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 SocketIO async_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版本的将会更流畅,如下图所示;

Flask 运用Xterm实现交互终端的更多相关文章

  1. 把sublime text打造成python交互终端(windows和Ubuntu)

    作者:tongqingliu 转载请注明出处:http://www.cnblogs.com/liutongqing/p/7015958.html 把sublime text打造成python交互终端 ...

  2. psql -- PostgreSQL 交互终端

    psql --  PostgreSQL 交互终端 用法:psql [option...] [dbname [username]] 描述:psql 是一个以终端为基础的 PostgreSQL 前端.它允 ...

  3. 类Flask实现前后端交互之代码聊天室

    前言 框架 项目目录及各自功能 流程图 后端 server backend exector 前端 ajax 页面更新 演示 简易应答模式 代理模式处理外部请求 后台日志 总结 前言 这两天老是做梦,全 ...

  4. flask之数据库的交互

    一:关系型数据库 mysql Flask-SQLAlchemy管理关系型数据库. mysql数据库引擎:url : mysql://username:passowrd@hostname/databas ...

  5. 编写一个简单的flask的前后端交互的网页(flask简单知识的讲解)

    实验原理: 1.什么是flask Flask是一个使用Python编写的轻量级Web应用框架,其WSGI工具采用Werkzeng,模板引擎使用Jinja2.Flask与 Django之间的区别就是Dj ...

  6. Flask form前后端交互消息闪现

    模拟场景如果当用户注册时输入错误而由于form表单是同步提的交跳转到另一个网页时提示注册失败这时用户还需返回注册页面重新填写大大降低了客户体验,消息闪现能伪装成异步(实际还是同步)就是自己提交给自己然 ...

  7. flask+script命令行交互工具

    Project name :Flask_Plan templates:templates static:static 首先说,我们flask比django方便的地方是所有的模块都可以自己选,你不喜欢s ...

  8. Jquery使用ajax与Flask后端进行数据交互

    最近做项目碰到一个坑,jquery使用ajax向flask传输数据的时候,在后端采用request.data无论如何都获取不到数据,代码如下: 前端: <script> function ...

  9. flask前后端数据交互

    1.后端如何得到前端数据1)如果前端提交的方法为POST:后端接收时要写methods=[‘GET’,‘POST’]xx=request.form.get(xx);xx=request.form[’‘ ...

  10. Docker - 终端交互

    进入容器交互终端 使用docker attach命令进入容器交互终端. 注意:如果多个窗口同时attach到同一个容器,那么所有窗口都会同步显示.如果某个窗口因命令阻塞时,那么其他窗口将无法执行操作. ...

随机推荐

  1. 开源流量检测引擎Dalton安装记录

    几个月之前照着官方文档安装过,一次性就成功,昨天重装了服务器再安装Dalton,怎么都安装不了 一直报错 ERROR: Service 'agent-suricata-current' failed ...

  2. spring-mvc系列:详解@RequestMapping注解(value、method、params、header等)

    目录 一.@RequestMapping注解的功能 二.@RequestMapping注解的位置 三.@RequestMapping注解的value属性 四.@RequestMapping注解的met ...

  3. 性能监控平台搭建(grafana+telegraf+influxdb) 及 配置 jmeter后端监听

    搞性能测试,可以搭建Grafana+Telegraf+InfluxDB 监控平台,监控服务器资源使用率.jmeter性能测试结果等. telegraf: 是一个用 Go 编写的代理程序,可收集系统和服 ...

  4. wineqq中接收文件的查看与移动

    在Ubuntu等linux系统中安装QQ都需要安装wine支持,而在使用时,会遇到qq接收到的文件无法直接进行操作等问题. 这时,我们发现直接对文件进行复制后,无法在Ubuntu目录中进行粘贴. 其实 ...

  5. Android RIL&IMS源码分析

    一.需求 1.了解IMS相关知识体系 2.RILD 与 RILJ.IMS回调消息的机制 二.相关概念 2.1 IMS IMS全称是IP Multimedia Subsystem,中文意义为IP多媒体子 ...

  6. 论文解读(MetaAdapt)《MetaAdapt: Domain Adaptive Few-Shot Misinformation Detection via Meta Learning》

    Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:MetaAdapt: Domain Adaptive Few-Shot Misinformation De ...

  7. 网络请求-Android篇(Okhttp和Retrofit)

    一.OkHttp的介绍和基本用法 OkHttp是一个流行的开源Java和Android应用程序的HTTP客户端.它由Square Inc.开发,提供了一种简单高效的方式来进行应用程序中的HTTP请求. ...

  8. 应用程序接口(API)安全的入门指南

    ​  什么是 API?​ 对于初学者来说,API 是指为两个不同的应用之间实现流畅通信,而设计的应用程序编程接口.它通常被称为应用程序的"中间人".由于我们需要保护用户的持有数据. ...

  9. tomcat配置域名绑定项目

    有时候我们需要根据访问的不同域名,对应tomcat中不同的项目例如:一个网站同时做了两套,pc版和手机版.手机版对应的域名是m.we-going.com,就需要在tomcat配置文件中加入以下代码:& ...

  10. EXE一机一码打包加密大师(EXE加密, 一机一码, 添加授权,添加静态密码,支持设置试用时间)

    EXE一机一码打包加密大师可以打包加密保护EXE文件,同时给EXE文件添加上一机一码认证,或者静态密码,不同的电脑打开加密后的文件需要输入不同的激活码才能正常使用,保护文件安全,方便向用户收费. 下载 ...