vue 中使用websocket和 xterm.js实现webssh

什么是webssh?

  • webssh 泛指一种技术可以在网页上实现一个 SSH 终端
  • ssh终端:用来通过ssh协议,连接服务器进行管理
  • 运维开发方向:堡垒机登录、线上机器管理(因为运维人员不可能24小时携带电脑)
  • 在线编程:提供一个编程环境

工作流程

在这里插入图片描述

安装依赖

npm i xterm

xterm是实现一个网页版的ssh的js库,目前更新到5.X的版本,由于项目比较老旧,安装的是3.X的版本,所以查看官网文档记得选对版本,xerm.js官网,如果是自己重新写,推荐用新的版本。值得注意的是:要学会看官网的文档,首页进去看到的文档教程比较少,更多详细的api和属性,放在了声明文件中: xterm.d.ts

引入

import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit'; // 让终端适应父容器的插件
Terminal.applyAddon(fit); // 加载fit 插件

代码实现

html

<div id="cluster-terminal"></div>

js核心代码

// 点击一个连接按钮调用
connect() {
// 通过weosocket参数传递的参数
 let params = {
   cluster: this.cluster,
   id: this.appId,
   container: this.containerId,
   host: this.rowInfo.node_ip,
   port: 900,
   cmd: this.select,
 };
 let config = this.$spaSdk.getPluginConfig(VUE_APP_PLUGIN_NAME);
 const obj = spaSdk.config.PLUGIN_CONFIGS_MAP[VUE_APP_PLUGIN_NAME];
 const wsurl = `${config['pod-websocket']}/v3/app/pod/terminal?${qs.stringify(params)}`;
// 初始化终端
 this.initTerm(wsurl);
},
// 初始化终端
initTerm(url) {
 this.websocket = new WebSocket(url);
  this.connected = true;
  this.websocket.onopen = evt => {
    console.log('连接打开。。。');
    // 创建一个终端实例 this.term
    this.term = new Terminal({ scrollback: 2000 });
	// 获取容器
    let terminalContainer = document.getElementById('cluster-terminal');
    while (terminalContainer.children.length) {
      terminalContainer.removeChild(terminalContainer.children[0]);
    }
    // 在容器中打开终端
    this.term.open(terminalContainer, true);
    // 给中端设置样式 cursorBlink 配置光标是否闪烁
    this.term.setOption('cursorBlink', true);

    var initialGeometry = this.term.proposeGeometry();
	// 获取终端的初始化的行和列,这个方法在文档中没有看到,通过查看其原型方法,确实存在
    var cols = initialGeometry.cols;
    var rows = initialGeometry.rows;
	// 让终端适配父容器
    this.term.fit();

    // 初始化的时候将 终端的宽和高传递给后端(非常重要!非常重要!非常重要!),让后端终端的尺寸设置和前端的一致,否则会出,宽度没有占满或者输入很长命令的时候不会自动换行而是将同行的从前面进行覆盖
    this.websocket.send('RESIZE_EXCE ' + rows + ' ' + cols);
	// 监听终端的输入事件,将输入的消息通过websocket传递给后端
    this.term.on('data', data => {
      this.websocket.send(data);
    });

    // this.term.resize(cols, rows);
	// 监听终端resize事件
    this.term.on('resize', size => {
    // 调整终端大小
      this.term.resize(size.cols, size.rows);
      // 将调整后的终端大小传递给后端,使后端的终端和前端的终端大小一致(非常重要!非常重要!非常重要!)
      this.websocket.send('RESIZE_EXCE ' + size.rows + ' ' + size.cols);
    });
	// 监听window的resize 事件,使终端去使用父容器的大小,这时候就会触发终端的resize事件
    window.onresize = () => {
      this.term.fit();
    };
    // 监听websocket返回消息事件
    this.websocket.onmessage = e => {
    //将返回的消息写入终端
      this.term.write(e.data);
      if (e.data === 'CONN CLOSE') {
        this.$Confirm.warning({
          modalProps: {
            confirmText: '确认',
            showCancel: false,
          },
          content: `因为pod删除等原因,连接已关闭!`,
          onOk() {},
        });
      }
    };

    this.websocket.onclose = evt => {
      console.log('连接关闭额', evt);
      this.connected = false;
    };
  };
},

值得注意的是:this.term.proposeGeometry(),在代码中看到了这句代码,因为不知道是什么意思,于是查看对应的文档,没有发现对应的api,难道是文档漏掉了?

最终效果

在这里插入图片描述

最大的坑

由于也是初次接触webssh和 xterm.js这个库,对于一些概念比较模糊不清,那么就很容易出现一些问题,让你丈二和尚,摸不着头脑,可能会出现前后端因为不懂相互踢皮球的问题;

  • 初始化终端的时候,在终端输入很长的命令,命令没法输入到终端的最右边就会从当前行的签名开始输入,不会换行,解决办法:当websocket 连接后且终端也打开后,将终端的尺寸一定要传递给后端,这个时候如果后端说我不需要这个参数,那就是他不懂,让他去查资料。。。

  • 当我们改变浏览器窗口大小的时候,终端中的内容不适应,不换行,消失等一些奇怪的问题,这都是因为后端的终端和前端不一致导致的,解决方法和上边同理。

参考文档

vue+xterm.js实现webssh踩坑之旅
xterm.js + vue + websocket实现终端功能(xterm 3.x+xterm 4.x)
Java实现WebSSH,自适应宽高、心跳检查、断开自动重连

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Vue 使用 xterm.jsWebSocket 实现终端,你需要将用户输入的命令发送给后端,然后将后端返回的结果输出到 xterm.js 终端。以下是一个简单的示例: ```html <template> <div id="terminal"></div> </template> <script> import { Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; export default { data() { return { socket: null, // WebSocket 实例 term: null, // Terminal 实例 }; }, mounted() { // 创建 WebSocket 实例 this.socket = new WebSocket('ws://localhost:8080'); // 创建 Terminal 实例 this.term = new Terminal(); const fitAddon = new FitAddon(); this.term.loadAddon(fitAddon); this.term.open(document.getElementById('terminal')); // 处理 WebSocket 消息 this.socket.onmessage = (event) => { this.term.write(event.data); }; // 处理输入事件 this.term.onData(data => { this.socket.send(data); }); // 调整终端大小 this.term.onResize(size => { const cols = size.cols; const rows = size.rows; this.socket.send(JSON.stringify({ type: 'resize', cols, rows })); }); // 发送 resize 消息 const cols = this.term.cols; const rows = this.term.rows; this.socket.send(JSON.stringify({ type: 'resize', cols, rows })); }, beforeDestroy() { // 关闭 WebSocket 连接 this.socket.close(); } } </script> ``` 以上代码,我们首先在 `mounted` 钩子函数创建了一个 WebSocket 实例和一个 Terminal 实例。然后我们为 WebSocket 实例添加了一个 `onmessage` 事件监听器,该监听器会在接收到服务器返回的消息时触发,我们在该事件处理函数将消息输出到终端。 接着,我们为 Terminal 实例添加了一个 `onData` 事件监听器,该监听器会在用户输入时触发,我们在该事件处理函数向服务器发送用户输入的命令。同时,我们还为 Terminal 实例添加了一个 `onResize` 事件监听器,该监听器会在终端大小调整时触发,我们在该事件处理函数向服务器发送终端大小变化的消息。 最后,我们在 `beforeDestroy` 钩子函数关闭了 WebSocket 连接。 需要注意的是,以上代码WebSocket 连接是通过 `ws://localhost:8080` 连接本地服务器的,你需要根据实际情况修改 WebSocket 连接地址。另外,代码的消息格式和处理逻辑也需要根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值