一次web模拟终端的简单实现

7,149 阅读3分钟

此文的背景是由于我之前刚好有一个项目配合运维做一个页面模拟终端能够ssh远程连接到指定服务器,类似devops的那一种吧,虽然也不是什么高大上的东西,我们经常会在一些云服务器后台上面看到并且使用过,但是之前也没有亲自实现过,所以用此文记录一下过程。

技术选型

此文不是造轮子....

此文不是造轮子....

此文不是造轮子....

此文不是造轮子....

...

其实现在前端业界已经覆盖了很多角度都有相对成熟的轮子了,所以我们肯定秉承拿来即用的最高原则。经过一番搜索,也很快的定位了xtermwww.npmjs.com/package/xte…, 据说这个vscode的终端也是用这个,这里我也没深究。

xterm

这里也就简单介绍一下,xterm.js是一个功能强大的浏览器端模拟终端的前端组件,支持typescript(敲黑板)。

然后它支持大部分的CLI应用(shell), 比如bash, vim等等。。。丰富的unicode支持,较多的扩展功能。整体来说还是蛮强大的。

vue

这个就不介绍了,我接手的时候运维自己用vue-cli建的项目。

代码撸起来

teamplate & style

首先是vue的template块和style块,超级简单的 页面标题副标题(显示目标服务器名称), 还有一个终端容器

script

重点来了(其实也敲级简单- -||)

首先简单的创建一个简单xterm示例并挂载到页面上.

然后这个时候你会发现只看到一个光标在上面闪但是不能输入任何东西。因为毕竟它不是一个真正的CLI程序,所以我们要启动一个真正的CLI程序并将交互呈现在这个模拟器上面,然后用websocket作为通信的桥梁。

这里我们将会引入两个xterm的扩展,分别是fitattach,更多的官方扩展参考github.com/xtermjs/xte….

  • fit, 使终端填充满容器.
  • attach, 通过websocket连接上一个正在运行进程的服务器。

代码如下:

通过applyAddon加载扩展, 然后在适当的时期显式调用xterm.fit()xterm.attach()

然后在组件的mounted生命周期里面建立websocket连接:

最后结合下面server块建立的服务,就能看到以下效果:

可以看到动图里面可以自由的输入命令跟操作本机终端是一样的效果!

最后把完整的组件代码放出来:

server

在使用扩展连接服务器之前,我们这里先准备一个demo服务,新建一个websocket的demo项目,安装node-pty模块和ws模块, 代码如下:

结语

这只是简单的实现了一个终端的投射,实际项目中还会有更细致和复杂的需求,可以深度挖掘xterm,或者自己写自定义扩展等等,因为只是demo代码,上面代码出现的一些不怎么好的写法还请各位看官勿喷, 感谢阅读。