- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
npm install xterm
<div id="terminal"></div>
import { Terminal } from 'xterm';
const term = new Terminal();
term.open(document.getElementById('terminal'));
term.write('Hello, World!');
term.onData(data => {
console.log(data);
});
以上只是最基础的使用方法。xterm.js 提供了许多其他功能,如主题定制、附加插件(例如 FitAddon 可以自动调整终端大小,WebLinksAddon 可以捕获 URL 并将其变为可点击链接)、设置光标样式、更改字体大小等等。你可以访问 xterm.js 的 GitHub (https://github.com/xtermjs/xterm.js)仓库 或者 文档 来获取更详细的信息.
。
package main
import (
"context"
"encoding/json"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/remotecommand"
"log"
"net/http"
)
// websocket 升级器配置
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
// WSClient 结构体,封装了 WebSocket 连接和 resize 通道,用于在 WebSocket 和 remotecommand 之间进行数据交换。
type WSClient struct {
// WebSocket 连接对象
ws *websocket.Conn
// TerminalSize 类型的通道,用于传输窗口大小调整事件
resize chan remotecommand.TerminalSize
}
// MSG 结构体,用于解析从 WebSocket 接收到的消息。
type MSG struct {
// 消息类型字段
MsgType string `json:"msg_type"`
Rows uint16 `json:"rows"`
Cols uint16 `json:"cols"`
// 输入消息的数据字段
Data string `json:"data"`
}
// WSClient 的 Read 方法,实现了 io.Reader 接口,从 websocket 中读取数据。
func (c *WSClient) Read(p []byte) (n int, err error) {
// 从 WebSocket 中读取消息
_, message, err := c.ws.ReadMessage()
if err != nil {
return 0, err
}
var msg MSG
if err := json.Unmarshal(message, &msg); err != nil {
return 0, err
}
// 根据消息类型进行不同的处理
switch msg.MsgType {
// 如果是窗口调整消息
case "resize":
winSize := remotecommand.TerminalSize{
Width: msg.Cols,
Height: msg.Rows,
}
// 将 TerminalSize 对象发送到 resize 通道
c.resize <- winSize
return 0, nil
// 如果是输入消息
case "input":
copy(p, msg.Data)
return len(msg.Data), err
}
return 0, nil
}
// WSClient 的 Write 方法,实现了 io.Writer 接口,将数据写入 websocket。
func (c *WSClient) Write(p []byte) (n int, err error) {
// 将数据作为文本消息写入 WebSocket
err = c.ws.WriteMessage(websocket.TextMessage, p)
return len(p), err
}
// Next WSClient 的 Next 方法,用于从 resize 通道获取下一个 TerminalSize 事件。
func (c *WSClient) Next() *remotecommand.TerminalSize {
// 从 resize 通道读取 TerminalSize 对象
size := <-c.resize
return &size
}
// podSSH 函数,这是主要的 SSH 功能逻辑,使用 kubernetes client-go 的 SPDY executor 来执行远程命令。
func podSSH(wsClient *WSClient, q query) {
// 使用 kubeconfig 文件初始化 kubernetes 客户端配置
// 请注意,你应该替换 ./config 为你的 kubeconfig 文件路径
restClientConfig, err := clientcmd.BuildConfigFromFlags("", "./config")
if err != nil {
log.Fatalf("Failed to build config: %v", err)
}
// 根据配置创建 kubernetes 客户端
clientSet, err := kubernetes.NewForConfig(restClientConfig)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
// 构造一个用于执行远程命令的请求
request := clientSet.CoreV1().RESTClient().Post().
Resource("pods").
Namespace(q.Namespace).
Name(q.PodName).
SubResource("exec").
VersionedParams(&corev1.PodExecOptions{
Container: q.ContainerName,
Command: []string{
q.Command,
},
Stdout: true,
Stdin: true,
Stderr: true,
TTY: true,
}, scheme.ParameterCodec)
// 创建 SPDY executor,用于后续的 Stream 操作
exec, err := remotecommand.NewSPDYExecutor(restClientConfig, "POST", request.URL())
if err != nil {
log.Fatalf("Failed to initialize executor: %v", err)
}
// 开始进行 Stream 操作,即通过 websocket 执行命令
err = exec.StreamWithContext(context.Background(), remotecommand.StreamOptions{
Stderr: wsClient,
Stdout: wsClient,
Stdin: wsClient,
Tty: true,
TerminalSizeQueue: wsClient,
})
if err != nil {
log.Fatalf("Failed to start stream: %v", err)
}
}
// query 结构体,用于解析和验证查询参数
type query struct {
Namespace string `form:"namespace" binding:"required"`
PodName string `form:"pod_name" binding:"required"`
ContainerName string `form:"container_name" binding:"required"`
Command string `form:"command" binding:"required"`
}
func main() {
router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.GET("/", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "ssh.html", nil)
})
// 设置 /ssh 路由
router.GET("/ssh", func(ctx *gin.Context) {
var r query
if err := ctx.ShouldBindQuery(&r); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{
"err": err.Error(),
})
return
}
// 将 HTTP 连接升级为 websocket 连接
ws, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil)
if err != nil {
log.Printf("Failed to upgrade connection: %v", err)
return
}
// 使用 podSSH 函数处理 websocket 连接
podSSH(&WSClient{
ws: ws,
resize: make(chan remotecommand.TerminalSize),
}, r)
})
router.Run(":9191")
}
https://github.com/PanJiaChen/vue-admin-template 。
https://github.com/xtermjs/xterm.js 。
下载vue-admin-template项目 。
https://github.com/PanJiaChen/vue-admin-template.git 。
安装xterm.js及插件 。
npm install
npm install xterm
npm install --save xterm-addon-web-links
npm install --save xterm-addon-fit
npm install -S xterm-style
打开vue-admin-template项目,在src/views目录下新建目录pod-ssh,在pod-ssh目录下新建index.vue代码如下 。
<template>
<div class="app-container">
<!-- 使用 Element UI 的表单组件创建一个带有标签和输入框的表单 -->
<el-form ref="form" :model="form" :inline="true" label-width="120px">
<el-form-item label="namespace"> <!-- namespace 输入框 -->
<el-input v-model="form.namespace" />
</el-form-item>
<el-form-item label="pod name"> <!-- pod 名称输入框 -->
<el-input v-model="form.pod_name" />
</el-form-item>
<el-form-item label="container name"> <!-- 容器名称输入框 -->
<el-input v-model="form.container_name" />
</el-form-item>
<el-form-item label="Command"> <!-- 命令选择框 -->
<el-select v-model="form.command" placeholder="bash">
<el-option label="bash" value="bash" />
<el-option label="sh" value="sh" />
</el-select>
</el-form-item>
<el-form-item> <!-- 提交按钮 -->
<el-button type="primary" @click="onSubmit">Create</el-button>
</el-form-item>
<div id="terminal" /> <!-- 终端视图容器 -->
</el-form>
</div>
</template>
<script>
import { Terminal } from 'xterm' // 导入 xterm 包,用于创建和操作终端对象
import { common as xtermTheme } from 'xterm-style' // 导入 xterm 样式主题
import 'xterm/css/xterm.css' // 导入 xterm CSS 样式
import { FitAddon } from 'xterm-addon-fit' // 导入 xterm fit 插件,用于调整终端大小
import { WebLinksAddon } from 'xterm-addon-web-links' // 导入 xterm web-links 插件,可以捕获 URL 并将其转换为可点击链接
import 'xterm/lib/xterm.js' // 导入 xterm 库
export default {
data() {
return {
form: {
namespace: 'default', // 默认命名空间为 "default"
command: 'bash', // 默认 shell 命令为 "bash"
pod_name: 'nginx', // 默认 Pod 名称为 "nginx"
container_name: 'nginx' // 默认容器名称为 "nginx"
},
}
},
methods: {
onSubmit() {
// 创建一个新的 Terminal 对象
const xterm = new Terminal({
theme: xtermTheme,
rendererType: 'canvas',
convertEol: true,
cursorBlink: true
})
// 创建并加载 FitAddon 和 WebLinksAddon
const fitAddon = new FitAddon()
xterm.loadAddon(fitAddon)
xterm.loadAddon(new WebLinksAddon())
// 打开这个终端,并附加到 HTML 元素上
xterm.open(document.getElementById('terminal'))
// 调整终端的大小以适应其父元素
fitAddon.fit()
// 创建一个新的 WebSocket 连接,并通过 URL 参数传递 pod, namespace, container 和 command 信息
const ws = new WebSocket('ws://127.0.0.1:9191/ssh?namespace=' + this.form.namespace + '&pod_name=' + this.form.pod_name + '&container_name=' + this.form.container_name + '&command=' + this.form.command)
// 当 WebSocket 连接打开时,发送一个 resize 消息给服务器,告诉它终端的尺寸
ws.onopen = function() {
ws.send(JSON.stringify({
msg_type: 'resize',
rows: xterm.rows,
cols: xterm.cols
}))
}
// 当从服务器收到消息时,写入终端显示
ws.onmessage = function(evt) {
xterm.write(evt.data)
}
// 当发生错误时,也写入终端显示
ws.onerror = function(evt) {
xterm.write(evt.data)
}
// 当窗口尺寸变化时,重新调整终端的尺寸,并发送一个新的 resize 消息给服务器
window.addEventListener('resize', function() {
fitAddon.fit()
ws.send(JSON.stringify({
msg_type: 'resize',
rows: xterm.rows,
cols: xterm.cols
}))
})
// 当在终端中键入字符时,发送一个 input 消息给服务器
xterm.onData((b) => {
ws.send(JSON.stringify({
msg_type: 'input',
data: b
}))
})
}
}
}
</script>
<style scoped>
.line{
text-align: center;
}
</style>
在src/router/index.js文件中增加路由 。
{
path: '/pod-ssh',
component: Layout,
children: [
{
path: 'pod-ssh',
name: 'SSH',
component: () => import('@/views/pod-ssh/index'),
meta: { title: 'SSH', icon: 'form' }
}
]
},
启动项目 。
npm install
npm run dev
前端全部代码 。
https://gitee.com/KubeSec/pod-webssh/tree/master/pod-webssh 。
。
在kubernetes中创建测试的Pod 。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
访问http://localhost:9528/#/pod-ssh/pod-ssh 。
。
最后此篇关于Gin+Xterm.js实现远程KubernetesPod(一)的文章就讲到这里了,如果你想了解更多关于Gin+Xterm.js实现远程KubernetesPod(一)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在对 Xterm 进行了大量研究之后,仔细研究了我已经认输的大量网页,并意识到这不是我自己可以解决的问题。 TrueType 与位图 是选项xterm*font用于仅指定位图字体并且是 *faceNa
我如何向 XTerm 终端发出输入结束信号。在我的例子中,我在 XTerm 控制台中运行一个 C++ 程序,我想通过按下一些键盘按钮组合来向程序发出输入结束信号。(我试过 Ctrl+D Ctrl+Z
我正在尝试 automate xterm它主要依赖于启动xterm时的-S选项。 来自手册页 -Sccn This option allows xterm to be used as an input
我的应用程序尝试执行根命令“sudo ifup eth0”和“sudo ifdown eth0”。但是它返回了一个错误“sudo:抱歉,你必须有一个 tty 才能运行 sudo”。因此,它需要一个 t
我有字体(由 fc-list 列出): /usr/share/fonts/misc/Inconsolata-dz for Powerline.otf: Inconsolata\-dz for Powe
我尝试在Reactjs中使用Xtermjs。但当我按照指南进行操作时。结果如下: 它应该显示没有顶部文本区域和文本“W”。 我的代码如下: import React from 'react'; imp
在尝试将我的终端程序设置为使用颜色时,我遇到了 xterm-color 和 xterm-256color 作为选项 - 即您可以设置您的 TERM 环境变量中的任何一个。 我想知道是否有人可以描述两者
我有一个 python 程序 (mypro.py),我想在其中同时在拓扑的所有主机上运行(即,无需转到每个 xtrem 窗口并键入 python mypro .py)。有没有办法通过使用脚本在 Min
不,不是 ASCII 图形,请参见此处的屏幕截图: http://en.wikipedia.org/wiki/W3m 这怎么可能? 我检查了源代码,它只打印字符序列。但是,我无法在 xterm 文档或
我想知道如何通过 execl 调用 Xterm。例如,对于下面的代码 #include #include #include #include #include #include #incl
我需要编写一个 bash 脚本,它会生成一个新的 xterm 窗口并在那边回显一些内容。我试过 echo "hello"| xterm &,它不起作用...此外,是否可以在新的 xterm 上执行任何
如果我像这样用 xterm 调用一个命令(在我的例子中是另一个脚本): xterm -e sh second.sh xterm 返回后$? 中的值是xterm 的退出状态码(通常对我来说是0)而不是我
我正在尝试为文件夹集合中的每个实例运行客户端和服务器。我试过这个命令: $ find ./-name "Makefile"-execdir xterm -title "Server"-e "timeo
我想在 C++ 中运行 xterm 终端来创建这样一个 Linux 进程 system("xterm -e adb start-server") adb 进程已创建,但在执行该命令后它会被终止。我试图
我安装了一个最小的 debian,我试图自己设置一切,所以我试图通过给它一些颜色来调整我的默认终端 Xterm,经过一些研究我发现这可以通过编辑.Xresources 文件,所以我可以用 Hexa 代
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎偏离主题,因为它缺乏足够的信息来诊断问题。 更详细地描述您的问题或 include a mini
如果在 linux 上使用子进程执行一个 xterm,而 xterm 又执行一些其他进程,Python (2.6.5) 似乎永远不会识别进程 (xterm) 已完成执行。 考虑以下代码: import
我正在编写一个打印彩色线条的程序,我用它做的越多,我就越发现自己在解决出现的换行问题。 这是一种用php编写的终端,这里是提示符: $return = readline("\033[44m\033[1
我正在使用 virtualenv(它设置了一些环境变量)。现在,我想生成一个具有相同环境的新终端窗口。如果我尝试: xterm & 我得到了一个新终端但是环境是默认环境,也就是当我在新终端上输入以下行
我经常使用 less 查看文件,并且想记住我刚刚在文件中看到的内容。但是,当我通过按 q 键退出 less 时,我的 xterm 窗口删除了 less 显示文件的页面,只显示我的命令提示符。 如何在退
我是一名优秀的程序员,十分优秀!