WebTerminal功能实现与代码演示(基于Golang和Xterm.js)

news2024/11/20 9:17:08

文章目录

  • 目的
  • 方案说说明
  • 实现过程与代码演示
    • 前端页面(Xterm.js)
    • 后端服务(Golang)
  • 编译与测试
  • 总结

目的

WebTerminal是一个比较有意思的功能,让我们可以脱离专门的软件,在浏览器中就可以与Linux设备进行交互。这篇文章将对这个功能做个简单的说明与演示。

例程地址如下:
https://github.com/NaisuXu/web-terminal-demo-with-golang-and-xterm

方案说说明

WebTerminal这个市面上叫法还是挺混乱的,大多数情况下还和WebSSH混在一起,两者本质上是有一些区别的。这里也把这两者混在一起列举下常见的几个方案:

在这里插入图片描述
上面这个情况常见都是用在运维管理等使用,可以在浏览器中管理多台设备或服务器。

在这里插入图片描述
上面这个情况也常用在运维管理等使用。

在这里插入图片描述
上面这个情况主要用于设备本身通过Web UI进行操作,想要更加高级的操作时可以直接通过终端进行。

这篇文章实现的是最后一种方式。另外因为我主要用在嵌入式Linux设备中,Web Server评估下来使用Golang是适应性和开发效率综合来说最好的。

实现过程与代码演示

前端页面(Xterm.js)

前端实现Terminal功能主要使用 Xterm.js 这个库,官方页面如下:
https://xtermjs.org/

VS Code中的中终端窗口就是使用这个库的,其中后端使用 node-pty 。

安装了Node.js的情况下新建项目目录并进入,然后初始化项目并下载xterm库:

npm init -y
npm install xterm

新建 index.html 文件,文件内容如下:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
    <script src="node_modules/xterm/lib/xterm.js"></script>
</head>
<body>
    <div id="terminal"></div>
    <script>
        const term = new Terminal();
        term.open(document.querySelector('#terminal'));
    </script>
</body>
</html>

这时候就可以测试 Xterm.js 的功能了,可以使用Terminal对象的 write 方法向终端窗口中输出内容,使用 onData 方法可以接收终端窗口中的键盘操作:
在这里插入图片描述

上面就是前端页面最核心的东西了,接下来只要处理与后端服务的数据交互即可。这里使用WebSocket方式,完成后的代码如下:

<!DOCTYPE html>
<html>

<head>
    <title>WebTerminal</title>
    <link rel="stylesheet" href="./node_modules/xterm/css/xterm.css" />
    <script src="./node_modules/xterm/lib/xterm.js"></script>
</head>

<body>
    <div style="width: 736px; height: 408px;">
        <!-- 目前版本的 Xterm 5.1.0 默认串口大小 24x80 -->
        <div id="terminal"></div>
    </div>
    <script>
        const term = new Terminal();

        term.open(document.querySelector('#terminal')); // 挂载

        const socket = new WebSocket(`ws://${window.location.host}/webterminal`); // 创建WebSocket连接

        term.onData((data) => { // 网页xterm窗口中有输入的数据
            // console.log('term.onData:', data);
            socket.send(data); // 通过WebSocket发送给服务器
        });
        
        socket.onmessage = (event) => { // 收到来自服务器的WebSocket消息
            // console.log('socket.onmessage:', event.data);
            term.write(event.data); // 向xterm对象写入数据
        };
    </script>
</body>

</html>

后端服务(Golang)

安装了Go的环境下,在刚才同目录中,使用下面命令初始化项目:

go mod init webterminal

新建 main.go 文件,文件内容如下:

package main

import (
	"embed"
	"net/http"
	"os/exec"

	"github.com/creack/pty"
	"github.com/olahol/melody"
)

//go:embed index.html node_modules/xterm/css/xterm.css node_modules/xterm/lib/xterm.js
var content embed.FS

func main() {
	c := exec.Command("sh") // 系统默认shell交互程序
	f, err := pty.Start(c)  // pty用于调用系统自带的虚拟终端
	if err != nil {
		panic(err)
	}

	m := melody.New() // melody用于实现WebSocket功能

	go func() { // 处理来自虚拟终端的消息
		for {
			buf := make([]byte, 1024)
			read, err := f.Read(buf)
			if err != nil {
				return
			}
			// fmt.Println("f.Read: ", string(buf[:read]))
			m.Broadcast(buf[:read]) // 将数据发送给网页
		}
	}()

	m.HandleMessage(func(s *melody.Session, msg []byte) { // 处理来自WebSocket的消息
		// fmt.Println("m.HandleMessage: ", string(msg))
		f.Write(msg) // 将消息写到虚拟终端
	})

	http.HandleFunc("/webterminal", func(w http.ResponseWriter, r *http.Request) {
		m.HandleRequest(w, r) // 访问 /webterminal 时将转交给melody处理
	})

	fs := http.FileServer(http.FS(content))
	http.Handle("/", http.StripPrefix("/", fs)) // 设置静态文件服务

	http.ListenAndServe("0.0.0.0:22333", nil) // 启动服务器,访问 http://本机(服务器)IP地址:22333/ 进行测试
}

代码比较简单,核心功能就是调用系统中的虚拟终端,然后通过WebSocket和网页进行双向通讯。

上面代码只是用于功能测试使用的,这个代码有个问题是并没有对每个客户端进行单独处理,所以打开多个网页时操作都会同步响应。

使用下面命令安装相关依赖:

go mod tidy

编译与测试

在项目目录下创建 build.sh 文件,文件内容如下:

#!/bin/sh
GOOS=linux GOARCH=amd64 go build -o webterminal_linux_x86-64
GOOS=linux GOARCH=arm GOARM=7 go build -o webterminal_linux_armv7
GOOS=linux GOARCH=arm GOARM=5 go build -o webterminal_linux_armv5

后面三行命令分别用于编译生成三个平台的程序,你也可以根据需要来编写。

使用下面命令进行编译(注意window中需要使用 git-bash 等操作):

# chmod +x ./build.sh
./build.sh

将编译生成的程序拷贝到对应的平台中就可以进行测试了。

linux_x86-64 (Ununtu 22.04 AMD Ryzen 5 PRO 4650U):
在这里插入图片描述

linux_armv5 (NUC980 Linux buildroot 5.10.103+ armv5tejl GNU/Linux):
在这里插入图片描述

这里没有测试 linux_armv7 平台,有条件的话可以找一个树莓派(4B)进行测试。

总结

基于Golang和Xterm.js实现WebTerminal功能原理上比较简单,实际应用时更多的是需要根据需求进行功能和使用上的优化。

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

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

相关文章

【运维知识进阶篇】集群架构-Rewrite重定向

Rewrite主要实现url地址重写&#xff0c;以及重定向&#xff0c;就是把传入web的请求重定向到其他url的过程。 分以下几种场景使用 1、地址跳转&#xff0c;用户访问一个URL&#xff0c;将其定向到另一个URL 2、协议跳转&#xff0c;用户通过http协议请求网站时&#xff0c;…

程序员不得不消化的基本概念:线程与协程,并行与并发

这是程序员的基本常识&#xff0c;这都搞不清楚&#xff0c;就不配为码农&#xff0c;就不配混CSDN。为人君者&#xff0c;招聘时可以以此为入门问题。 名词解释 在中文里&#xff0c;并发与并行很难望文生义&#xff0c;从字面上很难了解确切含义&#xff0c;貌似区别不大&am…

单机Redis、Redis持久化、Redis主从模式、Redis哨兵模式、Redis分片集群

一、单机Redis 数据库分类&#xff1a; 到目前为止&#xff0c;所有数据库分为两大类&#xff1a; RDBMS&#xff1a;关系型数据库&#xff0c;即传统数据库。 像MySQL、SQLServer、DB2、Sybase、SQLite、Oracle等等 以表的形式存储数据&#xff0c;表与表之间要维护数据的关系…

为什么投稿 SCI 被审稿人通过,又被编辑拒收?

有些作者在投稿过程中会遇到各种坑&#xff0c;不过有一种坑却最让作者痛心疾首&#xff0c;不知道大家有没有遇到过这样的状况&#xff1a; 审稿人建议接收&#xff0c;编辑却拒稿了&#xff1b; 或者审稿人建议拒稿&#xff0c;编辑却让自己改改再投&#xff1f; 有国外学者…

微服务: Seata AT springCloud整合分布式事务以配置方式(中篇)

目录 上篇: 安装seata 并启动成功的传送门 1. 前言: 2. springCloud 使用seata at 的步骤如下 第一步 查看springCloud版本 第二步添加maven依赖 第三步 添加yml配置 第四步: 配置数据源(druid) 第五步 修复一个警告 第六步: 启动后 看看日志是否成功 上篇: 安装seat…

边缘计算盒子功能介绍,为什么要用边缘计算盒子?

边缘计算盒子&#xff08;Edge Computing Box&#xff09;是一种用于边缘计算设备。边缘计算是一种分布式计算模型&#xff0c;它将计算和数据处理能力从传统的集中式云计算数据中心延伸到网络边缘的设备上&#xff0c;以便更快地响应实时数据处理需求和减少对云服务的依赖。 边…

HardenedVault 推出 Linux 安全加固版

导读HardenedVault 于 AWS 云平台上推出 Linux 安全加固版&#xff0c;该产品可以通过实施CIS和STIG基准来帮助您实现合规要求&#xff08;PCI-DSS和GDPR&#xff09;。 Shawn the R0ck 写道&#xff1a;HardenedVault自从 2022 年 7 月在 Amazon Web Services (AWS)推出了 Har…

Vscode运行Html的插件以及快速编写Html框架

然后我们点击创建文件&#xff0c;记住要以.html结尾 输入英文感叹号回车就行&#xff08;记住要英文&#xff09; 好了&#xff0c;希望小伙伴能快速入手VsCode&#xff0c;很好用的一款开源免费软件

基于Android的校园外卖系统app

一、项目介绍 Android客户端功能描述&#xff1a; 1&#xff1a;登录注册&#xff1a;用户可以通过自己的信息进行账号的注册 2&#xff1a;商家查看&#xff1a;查看发布的外卖商家信息 3&#xff1a;商家详情&#xff1a;用户点击某一个商家之后可以查看商家的地址和联系方…

AI人工智能在Python中构建回归器的原理、优缺点、应用场景和实现方法

回归器&#xff08;Regressor&#xff09;是一种常用的机器学习算法&#xff0c;可以用于预测数值型变量的值。在人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;领域中&#xff0c;回归器是一种高效的算法&#xff0c;可以用于许多应用领域&#…

6.4.4最短路径问题-Floyd算法

原来在邻接矩阵种v2使无法到达v1的 但如果我们把v0作为中转站 不断增加中转点&#xff08;1个中转点&#xff09; 这里的path的值是中转点 v1到v2之间是没有中转点的。 这只是以一个中转点&#xff0c;more 路走得越多&#xff0c;会越来越小 广度优先遍历算法是遍历顶点和边…

(二)ArcGIS空间数据的转换与处理——矢量数据变换

ArcGIS空间数据的转换与处理——矢量数据变换 目录 ArcGIS空间数据的转换与处理——矢量数据变换 1.空间校正2.边匹配 数据变换是指对数据进行诸如放大、缩小、翻转、移动、扭曲等几何位置、形状和方位的改变等操作。对 矢量数据的相应操作可以通过 ArcMap 中空间较正 (Spatia…

录制屏幕怎么设置?怎么录制高画质的视频?

在今天的数字时代&#xff0c;屏幕录制已经成为了日常工作中不可或缺的一部分。许多人需要在电脑上录制屏幕来制作教程视频、演示文稿或者是游戏录像。本文将介绍如何在电脑上录制屏幕并获得高画质的视频。 屏幕录制软件的选择 要在电脑上录制高画质的视频&#xff0c;首先需要…

【1】机器学习

目录 1 机器学习概述 1.1 定义 1.2 基本方法 1.3 基本概念 1.4 有监督学习 1.5 无监督学习 1.6 过度拟合问题 模型过于复杂(例如参数过多) 正则化 1.7 模型选择 交叉验证 K折交叉验证 2 机器学习常用工具 3 Scikit-learn 3.1 基本流程 3.2 Scikit-learn常用函数 3.…

csdn Markdown编辑器

文章目录 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个注脚注释也是…

云视如何实现流量转化

云视如何实现流量转化 大家好我是小鱼 小伙伴很好奇 云视除了直播带货 打赏&#xff0c;广告 还有哪些方式 可以实现流量转化 今天我和大家分享一下这个话题 接下来我们要讲讲 我们要用的工具 优惠券 适用于刺激消费回流&#xff0c;构建闭环消费圈。 课程赠送 趣味推广营销&am…

平台使用篇 | 批处理(bat)脚本使用教程(三)

导读 本讲针对RflySim平台的一些特点简要介绍了平台使用批处理技术的原因&#xff0c;并根据CopterSim中仿真功能区的参数设置阐述了批处理技术在平台中的具体运用。 平台使用篇 | 批处理(bat)脚本使用教程(三&#xff09; RflySim平台使用批处理技术的原因 ①调用多个软件Rf…

吲哚菁绿ICG-Amine/NH2荧光标记和成像1686147-55-6

ICG-Amine是一种荧光染料&#xff0c;ICG-Amine具有良好的荧光性能&#xff0c;可用于生物医学研究中的荧光标记和成像。ICG-Amine的物理性质如下&#xff1a;化学式&#xff1a;C47H56N4O4S&#xff0c;分子量为773.04&#xff0c;外观&#xff1a;深绿色粉末溶解性&#xff1…

代码随想录算法训练营第四十八天 | 树形dp

198.打家劫舍 文档讲解&#xff1a;代码随想录 (programmercarl.com) 状态&#xff1a;看了“决定dp[i]的因素才做出来"。 思路 当前房屋偷与不偷取决于 前一个房屋和前两个房屋是否被偷了。 所以这里就更感觉到&#xff0c;当前状态和前面状态会有一种依赖关系&#xf…

点云重建总结

几何处理和三维视觉 几何处理&#xff1a;是一种计算的方法研究世界中的物理对象&#xff0c;通过硬件扫描生成物理对象的三维模型然后做各种处理和分析。 三维视觉&#xff1a;传统的3D视觉是指从图像中恢复底层的三维结构。 1 几何重建 1.1几何重建的基本流程 扫描&…