From d12d70c01754f746af6815f7a03517628ac18008 Mon Sep 17 00:00:00 2001 From: bwcx_jzy Date: Sat, 10 Jun 2023 22:14:11 +0800 Subject: [PATCH] =?UTF-8?q?feat=20SSH=20=E5=88=97=E8=A1=A8=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=98=BE=E7=A4=BA=20docker=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 6 +++ CHANGELOG-BETA.md | 6 +++ .../func/assets/model/MachineSshModel.java | 4 ++ .../func/assets/server/MachineSshServer.java | 12 ++++++ .../config_default/ssh/monitor-script.sh | 6 +++ .../resources/sql-view/alter.all.v1.3.csv | 1 + web-vue/src/components/logView/view-pre.vue | 40 ++++++++++++++++--- web-vue/src/components/terminal/index.vue | 7 +++- web-vue/src/pages/dispatch/logReadView.vue | 24 +++++------ web-vue/src/pages/docker/log-view.vue | 4 ++ .../node/node-layout/other/script-console.vue | 13 ++++-- .../node-layout/project/project-console.vue | 14 +++++-- .../node-layout/project/project-file-read.vue | 16 +++++--- .../src/pages/node/node-layout/system/log.vue | 10 +++++ web-vue/src/pages/script/script-console.vue | 14 +++++-- .../src/pages/system/assets/ssh/ssh-list.vue | 32 ++++++++++++--- web-vue/src/pages/system/log.vue | 12 +++--- web-vue/src/pages/system/upgrade.vue | 13 ++++-- 18 files changed, 185 insertions(+), 49 deletions(-) diff --git a/.editorconfig b/.editorconfig index 4cd3fcc16..a6b6c656f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -46,6 +46,12 @@ max_line_length = off [*.bat] end_of_line = crlf +[*.sh] +end_of_line = lf +indent_style = space +indent_size = 2 +max_line_length = off + [*.{vue,js,ts}] indent_style = space indent_size = 2 diff --git a/CHANGELOG-BETA.md b/CHANGELOG-BETA.md index f1bb48ca3..09c5cf4d9 100644 --- a/CHANGELOG-BETA.md +++ b/CHANGELOG-BETA.md @@ -4,6 +4,7 @@ ### 🐣 新增功能 +1. 【server】新增 SSH 列表支持显示 docker 版本信息 ### 🐞 解决BUG、优化功能 @@ -12,6 +13,11 @@ 3. 【server】优化 web socket 会话关闭显示分类 4. 【server】优化 页面滚动条样式 5. 【server】优化 编辑关联分发,选择项目下拉框不能显示项目全名称(tooltip)(感谢@LYY) +6. 【server】优化 监听页面关闭事件,主动关闭 websocket + +### ⚠️ 注意 + +1. 如果自定义过 SSH 监控脚本需要自行同步获取 docker 信息脚本 ------ diff --git a/modules/server/src/main/java/org/dromara/jpom/func/assets/model/MachineSshModel.java b/modules/server/src/main/java/org/dromara/jpom/func/assets/model/MachineSshModel.java index 7a8ca64b9..3ecb52273 100644 --- a/modules/server/src/main/java/org/dromara/jpom/func/assets/model/MachineSshModel.java +++ b/modules/server/src/main/java/org/dromara/jpom/func/assets/model/MachineSshModel.java @@ -164,6 +164,10 @@ public class MachineSshModel extends BaseGroupNameModel implements ISshInfo { * java 版本 */ private String javaVersion; + /** + * 服务器中的 docker 信息 + */ + private String dockerInfo; public MachineSshModel(String id) { setId(id); diff --git a/modules/server/src/main/java/org/dromara/jpom/func/assets/server/MachineSshServer.java b/modules/server/src/main/java/org/dromara/jpom/func/assets/server/MachineSshServer.java index 94b268251..fcf10a632 100644 --- a/modules/server/src/main/java/org/dromara/jpom/func/assets/server/MachineSshServer.java +++ b/modules/server/src/main/java/org/dromara/jpom/func/assets/server/MachineSshServer.java @@ -39,6 +39,7 @@ import cn.hutool.cron.task.Task; import cn.hutool.db.Entity; import cn.hutool.extra.ssh.JschUtil; import cn.keepbx.jpom.Type; +import com.alibaba.fastjson2.JSONObject; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import lombok.Lombok; @@ -295,6 +296,17 @@ public class MachineSshServer extends BaseDbService implements } update.setJavaVersion(this.getFirstValue(map, "java version")); update.setJpomAgentPid(Convert.toInt(this.getFirstValue(map, "jpom agent pid"))); + // + String dockerPath = this.getFirstValue(map, "docker path"); + String dockerVersion = this.getFirstValue(map, "docker version"); + if (StrUtil.isAllNotEmpty(dockerVersion, dockerPath)) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("version", dockerVersion); + jsonObject.put("path", dockerPath); + update.setDockerInfo(jsonObject.toString()); + } else { + update.setDockerInfo(StrUtil.EMPTY); + } this.updateById(update); } diff --git a/modules/server/src/main/resources/config_default/ssh/monitor-script.sh b/modules/server/src/main/resources/config_default/ssh/monitor-script.sh index 18c6cc4db..7f45c2264 100644 --- a/modules/server/src/main/resources/config_default/ssh/monitor-script.sh +++ b/modules/server/src/main/resources/config_default/ssh/monitor-script.sh @@ -72,3 +72,9 @@ df -k | awk 'NR>1' | awk '/^\/dev/{print "disk info:"$1":"$2":"$3}' jpom_agent_pid=$(getPid "${JPOM_AGENT_PID_TAG}") echo "jpom agent pid:$jpom_agent_pid" echo "java version:$(command -v java)" + +docker_path=$(command -v docker) +if [[ $docker_path != "" ]]; then + echo "docker path:$docker_path" + echo "docker version:$(docker -v)" +fi diff --git a/modules/server/src/main/resources/sql-view/alter.all.v1.3.csv b/modules/server/src/main/resources/sql-view/alter.all.v1.3.csv index 5f38e2c18..e6a3838c9 100644 --- a/modules/server/src/main/resources/sql-view/alter.all.v1.3.csv +++ b/modules/server/src/main/resources/sql-view/alter.all.v1.3.csv @@ -57,3 +57,4 @@ ADD,PROJECT_INFO,workspaceName,String,50,,工作空间名称,false ADD,SCRIPT_EXECUTE_LOG,workspaceName,String,50,,工作空间名称,false ALTER,REPOSITORY,password,String,255,,登录密码,false ADD,WORKSPACE,group,String,50,,分组,false +ADD,MACHINE_SSH_INFO,dockerInfo,String,255,,服务器中的 docker 信息,false diff --git a/web-vue/src/components/logView/view-pre.vue b/web-vue/src/components/logView/view-pre.vue index 1dcda4b5b..6d930b56f 100644 --- a/web-vue/src/components/logView/view-pre.vue +++ b/web-vue/src/components/logView/view-pre.vue @@ -64,6 +64,7 @@ export default { idInc: 0, visibleStartIndex: -1, itemHeight: 24, + inited: false, uniqueId: `component_${Math.random().toString(36).substring(2, 15)}`, }; }, @@ -74,10 +75,28 @@ export default { }, showList() { const element = document.querySelector(`#${this.uniqueId}`); - - let result = [...this.dataArray]; + let result; + if (this.inited) { + result = this.dataArray.length + ? [...this.dataArray] + : [ + { + text: this.defText, + id: "0-def", + }, + ]; + } else { + // 还没有 dom 对象 + result = [ + { + text: "loading..................", + id: "0-def", + }, + ]; + } let warp = false; if (element) { + // 填充空白,避免无内容 页面背景太低 const min = Math.ceil(element.clientHeight / this.itemHeight); const le = min - result.length; for (let i = 0; i < le; i++) { @@ -89,6 +108,7 @@ export default { } } if (!warp) { + // 最后填充一行空白,避免无法看到滚动条 result = result.concat([ { id: "system-warp-end:1", @@ -105,7 +125,15 @@ export default { // set() {}, // }, }, - mounted() {}, + mounted() { + const timer = setInterval(() => { + const element = document.querySelector(`#${this.uniqueId}`); + if (element) { + this.inited = true; + clearInterval(timer); + } + }, 200); + }, methods: { scrollToBottom() { const element = document.querySelector(`#${this.uniqueId}`); @@ -122,9 +150,9 @@ export default { return setTimeout(cb, 10); }; } - var scrollTop = element.scrollTop; - var step = function () { - var distance = position - scrollTop; + let scrollTop = element.scrollTop; + const step = function () { + const distance = position - scrollTop; scrollTop = scrollTop + distance / 5; if (Math.abs(distance) < 1) { element.scrollTop = position; diff --git a/web-vue/src/components/terminal/index.vue b/web-vue/src/components/terminal/index.vue index 0a6c947a1..b66c65a9b 100644 --- a/web-vue/src/components/terminal/index.vue +++ b/web-vue/src/components/terminal/index.vue @@ -45,6 +45,11 @@ export default { this.initSocket(); }, 200); }); + // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 + window.onbeforeunload = () => { + this.socket?.close(); + this.dispose(); + }; }, beforeDestroy() { this.socket?.close(); @@ -129,7 +134,7 @@ export default { this.sendJson({ data: "resize", cols: this.cols, rows: this.rows, wp: this.wp, hp: this.hp }); // 创建心跳,防止掉线 this.heart = setInterval(() => { - let op = { + const op = { data: "jpom-heart", }; this.sendJson(op); diff --git a/web-vue/src/pages/dispatch/logReadView.vue b/web-vue/src/pages/dispatch/logReadView.vue index 276482d53..882de18be 100644 --- a/web-vue/src/pages/dispatch/logReadView.vue +++ b/web-vue/src/pages/dispatch/logReadView.vue @@ -217,23 +217,23 @@ export default { }); this.activeTagKey = this.temp.cacheData.useNodeId + "," + this.temp.cacheData.useProjectId; // console.log(cacheData); + // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 + window.onbeforeunload = () => { + this.close(); + }; }, beforeDestroy() { - Object.keys(this.socketCache).forEach((item) => { - clearInterval(this.socketCache[item].heart); - }); - }, - destroyed() { - Object.keys(this.socketCache).forEach((item) => { - clearInterval(this.socketCache[item].heart); - }); + this.close(); }, methods: { + close() { + Object.keys(this.socketCache).forEach((item) => { + clearInterval(this.socketCache[item].heart); + this.socketCache[item].socket?.close(); + }); + }, initWebSocket(id, url) { - let socket; - if (!socket || socket.readyState !== socket.OPEN || socket.readyState !== socket.CONNECTING) { - socket = new WebSocket(url); - } + const socket = new WebSocket(url); socket.onerror = (err) => { console.error(err); diff --git a/web-vue/src/pages/docker/log-view.vue b/web-vue/src/pages/docker/log-view.vue index 0d291afa4..258e46f6f 100644 --- a/web-vue/src/pages/docker/log-view.vue +++ b/web-vue/src/pages/docker/log-view.vue @@ -61,6 +61,10 @@ export default { }, mounted() { this.initWebSocket(); + // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 + window.onbeforeunload = () => { + this.close(); + }; }, beforeDestroy() { this.close(); diff --git a/web-vue/src/pages/node/node-layout/other/script-console.vue b/web-vue/src/pages/node/node-layout/other/script-console.vue index 07925e4a5..6197ec93c 100644 --- a/web-vue/src/pages/node/node-layout/other/script-console.vue +++ b/web-vue/src/pages/node/node-layout/other/script-console.vue @@ -92,14 +92,19 @@ export default { } else { this.commandParams = []; } + // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 + window.onbeforeunload = () => { + this.close(); + }; }, beforeDestroy() { - if (this.socket) { - this.socket.close(); - } - clearInterval(this.heart); + this.close(); }, methods: { + close() { + this.socket?.close(); + clearInterval(this.heart); + }, // 初始化 initWebSocket() { this.logContext = ""; diff --git a/web-vue/src/pages/node/node-layout/project/project-console.vue b/web-vue/src/pages/node/node-layout/project/project-console.vue index 3433c2aa9..9980d89a8 100644 --- a/web-vue/src/pages/node/node-layout/project/project-console.vue +++ b/web-vue/src/pages/node/node-layout/project/project-console.vue @@ -105,14 +105,20 @@ export default { mounted() { this.loadProject(); this.initWebSocket(); + // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 + window.onbeforeunload = () => { + this.close(); + }; }, beforeDestroy() { - if (this.socket) { - this.socket.close(); - } - clearInterval(this.heart); + this.close(); }, methods: { + close() { + this.socket?.close(); + + clearInterval(this.heart); + }, // 加载项目 loadProject() { const params = { diff --git a/web-vue/src/pages/node/node-layout/project/project-file-read.vue b/web-vue/src/pages/node/node-layout/project/project-file-read.vue index 2a1a342ba..7432d61d8 100644 --- a/web-vue/src/pages/node/node-layout/project/project-file-read.vue +++ b/web-vue/src/pages/node/node-layout/project/project-file-read.vue @@ -67,14 +67,20 @@ export default { mounted() { // this.loadProject(); this.initWebSocket(); + // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 + window.onbeforeunload = () => { + this.close(); + }; }, beforeDestroy() { - if (this.socket) { - this.socket.close(); - } - clearInterval(this.heart); + this.close(); }, methods: { + close() { + this.socket?.close(); + + clearInterval(this.heart); + }, // 初始化 initWebSocket() { //this.logContext = ""; @@ -99,7 +105,7 @@ export default { clearInterval(this.heart); }; this.socket.onmessage = (msg) => { - this.$refs.logView.appendLine(msg.data); + this.$refs.logView?.appendLine(msg.data); clearInterval(this.heart); // 创建心跳,防止掉线 diff --git a/web-vue/src/pages/node/node-layout/system/log.vue b/web-vue/src/pages/node/node-layout/system/log.vue index 7d4b85293..8a7bb6263 100644 --- a/web-vue/src/pages/node/node-layout/system/log.vue +++ b/web-vue/src/pages/node/node-layout/system/log.vue @@ -72,8 +72,18 @@ export default { watch: {}, created() { this.loadData(); + // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 + window.onbeforeunload = () => { + this.close(); + }; + }, + beforeDestroy() { + this.close(); }, methods: { + close() { + this.socket?.close(); + }, // 加载数据 loadData() { this.list = []; diff --git a/web-vue/src/pages/script/script-console.vue b/web-vue/src/pages/script/script-console.vue index 40e859aa5..88d8c43e6 100644 --- a/web-vue/src/pages/script/script-console.vue +++ b/web-vue/src/pages/script/script-console.vue @@ -90,14 +90,20 @@ export default { } else { this.commandParams = []; } + // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 + window.onbeforeunload = () => { + this.close(); + }; }, beforeDestroy() { - if (this.socket) { - this.socket.close(); - } - clearInterval(this.heart); + this.close(); }, methods: { + close() { + this.socket?.close(); + + clearInterval(this.heart); + }, // 初始化 initWebSocket() { this.logContext = ""; diff --git a/web-vue/src/pages/system/assets/ssh/ssh-list.vue b/web-vue/src/pages/system/assets/ssh/ssh-list.vue index db5106f0f..81fcde47f 100644 --- a/web-vue/src/pages/system/assets/ssh/ssh-list.vue +++ b/web-vue/src/pages/system/assets/ssh/ssh-list.vue @@ -60,14 +60,29 @@ +