mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-12-02 20:08:40 +08:00
fix ssh delete
This commit is contained in:
parent
0fae9b0e2c
commit
3031eeef9c
@ -26,6 +26,8 @@
|
||||
10. 【server】升级 SpringBoot 版本 2.6.2
|
||||
11. 脚本模版执行目录修改为脚本所在目录
|
||||
12. 【server】SSH 命令模版支持取消默认加载环境变量:`#disabled-template-auto-evn`
|
||||
13. 【server】优化页面分页交互逻辑,只有一页不显示分页条
|
||||
14. 【server】修复删除 SSH 没有删除执行日志
|
||||
|
||||
> 特别提醒:强烈建议升级该版本,当前版本完善了权限拦截相关问题
|
||||
------
|
||||
|
@ -92,8 +92,9 @@ public class IndexController extends BaseAgentController {
|
||||
List<NodeScriptModel> list = nodeScriptServer.list();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("javaVirtualCount", JvmUtil.getJavaVirtualCount());
|
||||
jsonObject.put("osName", JpomManifest.getInstance().getOsName());
|
||||
jsonObject.put("jpomVersion", JpomManifest.getInstance().getVersion());
|
||||
JpomManifest instance = JpomManifest.getInstance();
|
||||
jsonObject.put("osName", instance.getOsName());
|
||||
jsonObject.put("jpomVersion", instance.getVersion());
|
||||
jsonObject.put("javaVersion", SystemUtil.getJavaRuntimeInfo().getVersion());
|
||||
// 获取JVM中内存总大小
|
||||
long totalMemory = SystemUtil.getTotalMemory();
|
||||
@ -105,7 +106,8 @@ public class IndexController extends BaseAgentController {
|
||||
jsonObject.put("count", CollUtil.size(nodeProjectInfoModels));
|
||||
jsonObject.put("scriptCount", CollUtil.size(list));
|
||||
// 运行时间
|
||||
jsonObject.put("runTime", JpomManifest.getInstance().getUpTime());
|
||||
jsonObject.put("runTime", instance.getUpTimeStr());
|
||||
jsonObject.put("runTimeLong", instance.getUpTime());
|
||||
return JsonMessage.getString(200, "", jsonObject);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ whitelistDirectory:
|
||||
# 白名单目录是否验证包含关系
|
||||
checkStartsWith: true
|
||||
log:
|
||||
# 自动备份控制台日志,防止日志文件过大,目前暂只支持linux 不停服备份
|
||||
# 自动备份控制台日志,防止日志文件过大,目前暂只支持linux 不停服备份,配置为 none 则不备份避免占用硬盘空间
|
||||
autoBackConsoleCron: 0 0/10 * * * ?
|
||||
# 当文件多大时自动备份
|
||||
autoBackSize: 50MB
|
||||
|
@ -263,11 +263,15 @@ public class JpomManifest {
|
||||
this.dataPath = dataPath;
|
||||
}
|
||||
|
||||
public String getUpTime() {
|
||||
public String getUpTimeStr() {
|
||||
long uptime = SystemUtil.getRuntimeMXBean().getUptime();
|
||||
return DateUtil.formatBetween(uptime, BetweenFormatter.Level.SECOND);
|
||||
}
|
||||
|
||||
public long getUpTime() {
|
||||
return SystemUtil.getRuntimeMXBean().getUptime();
|
||||
}
|
||||
|
||||
public String getOsName() {
|
||||
return osName;
|
||||
}
|
||||
|
@ -227,7 +227,10 @@ public class SshController extends BaseServerController {
|
||||
public String del(@ValidatorItem(value = ValidatorRule.NOT_BLANK) String id) {
|
||||
boolean checkSsh = buildInfoService.checkReleaseMethod(id, BuildReleaseMethod.Ssh);
|
||||
Assert.state(!checkSsh, "当前ssh存在构建项,不能删除");
|
||||
sshService.delByKey(id, getRequest());
|
||||
HttpServletRequest request = getRequest();
|
||||
sshService.delByKey(id, request);
|
||||
//
|
||||
int logCount = sshTerminalExecuteLogService.delByWorkspace(request, entity -> entity.set("sshId", id));
|
||||
return JsonMessage.getString(200, "操作成功");
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,10 @@ public class NodeMonitor {
|
||||
nodeStatModel.setNetworkTime(statusData.getIntValue("networkTime"));
|
||||
nodeStatModel.setJpomVersion(statusData.getString("jpomVersion"));
|
||||
nodeStatModel.setOsName(statusData.getString("osName"));
|
||||
nodeStatModel.setUpTimeStr(statusData.getString("runTime"));
|
||||
String runTime = statusData.getString("runTime");
|
||||
String runTimeLong = statusData.getString("runTimeLong");
|
||||
// 兼容数据
|
||||
nodeStatModel.setUpTimeStr(StrUtil.emptyToDefault(runTimeLong, runTime));
|
||||
nodeStatModel.setFailureMsg(StrUtil.emptyToDefault(statusData.getString("failureMsg"), StrUtil.EMPTY));
|
||||
//
|
||||
Integer statusInteger = statusData.getInteger("status");
|
||||
|
@ -367,10 +367,7 @@ public class ServerExtConfigBean implements DisposableBean {
|
||||
|
||||
public int getNodeHeartSecond() {
|
||||
int integer = ObjectUtil.defaultIfNull(nodeHeartSecond, 30);
|
||||
if (integer <= 0) {
|
||||
return integer;
|
||||
}
|
||||
return integer;
|
||||
return Math.max(integer, 5);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,7 +80,7 @@ node:
|
||||
system:
|
||||
# cron 定时器是否开启匹配秒
|
||||
timerMatchSecond: false
|
||||
# 节点心跳监控时间 (需要大于零) 单位秒
|
||||
# 节点心跳监控时间 (需要大于零) 单位秒 最小配置 5秒
|
||||
nodeHeartSecond: 30
|
||||
# 旧包文件保留个数
|
||||
oldJarsCount: 2
|
||||
|
@ -34,13 +34,28 @@
|
||||
<a-select v-model="listQuery['order_field']" allowClear placeholder="请选择排序字段" class="search-input-item">
|
||||
<a-select-option value="networkTime">网络延迟</a-select-option>
|
||||
<a-select-option value="occupyCpu">cpu</a-select-option>
|
||||
<a-select-option value="occupyDisk">disk</a-select-option>
|
||||
<a-select-option value="occupyMemoryUsed">memoryUsed</a-select-option>
|
||||
<a-select-option value="occupyMemory">memory</a-select-option>
|
||||
<a-select-option value="occupyDisk">硬盘</a-select-option>
|
||||
<a-select-option value="occupyMemoryUsed">内存Used</a-select-option>
|
||||
<a-select-option value="occupyMemory">内存</a-select-option>
|
||||
</a-select>
|
||||
<a-tooltip title="按住 Ctr 或者 Alt 键点击按钮快速回到第一页">
|
||||
<a-button :loading="loading" type="primary" @click="loadData">搜索</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottom">
|
||||
<template slot="title">
|
||||
<div>
|
||||
<ul>
|
||||
<li>监控数据目前采用原生命令获取,和真实情况有一定差异可以当做参考依据</li>
|
||||
<li>监控频率可以到服务端配置文件中修改</li>
|
||||
<li>悬停到仪表盘上显示具体含义</li>
|
||||
<li>点击仪表盘查看监控历史数据</li>
|
||||
<li>点击延迟可以查看对应节点网络延迟历史数据</li>
|
||||
<li>只有 linux 系统才有内存Used 值</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<a-icon type="question-circle" theme="filled" />
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-space>
|
||||
@ -51,7 +66,11 @@
|
||||
<template slot="title">
|
||||
<a-row :gutter="[4, 0]">
|
||||
<a-col :span="17" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap">
|
||||
<a-tooltip :title="`${item.name} ${item.url}`">
|
||||
<a-tooltip>
|
||||
<template slot="title">
|
||||
<div>节点名称:{{ item.name }}</div>
|
||||
<div>节点地址:{{ item.url }}</div>
|
||||
</template>
|
||||
{{ item.name }}
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
@ -63,8 +82,8 @@
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<a-space>
|
||||
<a-row :gutter="[16, 0]" style="margin-left: -16px">
|
||||
<a-col :span="8">
|
||||
<a-tooltip @click="item.status === 4 ? null : handleHistory(item, 'nodeTop')" :title="`CPU 占用率:${item.occupyCpu}%`">
|
||||
<a-progress
|
||||
type="circle"
|
||||
@ -79,6 +98,8 @@
|
||||
:percent="item.occupyCpu"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-tooltip @click="item.status === 4 ? null : handleHistory(item, 'nodeTop')" :title="`硬盘占用率:${item.occupyDisk}%`">
|
||||
<a-progress
|
||||
type="circle"
|
||||
@ -93,6 +114,8 @@
|
||||
:percent="item.occupyDisk"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-tooltip @click="item.status === 4 ? null : handleHistory(item, 'nodeTop')" :title="`内存占用率:${item.occupyDisk}%`">
|
||||
<a-progress
|
||||
:width="80"
|
||||
@ -107,16 +130,16 @@
|
||||
:percent="item.occupyMemoryUsed && item.occupyMemoryUsed !== -1 ? item.occupyMemoryUsed : item.occupyMemory"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-space direction="vertical"> <div></div></a-space>
|
||||
<a-row :gutter="[16, 8]">
|
||||
<a-row :gutter="[16, 8]" style="text-align: center; margin-left: -16px">
|
||||
<a-col :span="8">
|
||||
<a-tooltip @click="item.status === 4 ? null : handleHistory(item, 'networkTime')" :title="`${item.status === 4 ? '' : '延迟' + item.networkTime + 'ms 点击查看历史趋势'}`">
|
||||
<a-tooltip @click="item.status === 4 ? null : handleHistory(item, 'networkTime')" :title="`${item.status === 4 ? '-' : '延迟' + item.networkTime + 'ms 点击查看历史趋势'}`">
|
||||
<a-statistic
|
||||
title="延迟"
|
||||
:value="item.networkTime"
|
||||
valueStyle="font-size: 14px;"
|
||||
valueStyle="font-size: 14px;overflow: hidden; text-overflow: ellipsis; white-space: nowrap"
|
||||
:formatter="
|
||||
(v) => {
|
||||
return item.networkTime === -1 ? '-' : item.networkTime + 'ms';
|
||||
@ -125,17 +148,31 @@
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
<a-col :span="16">
|
||||
<a-statistic
|
||||
title="运行时间"
|
||||
:value="item.networkTime"
|
||||
valueStyle="font-size: 14px;"
|
||||
:formatter="
|
||||
(v) => {
|
||||
return item.upTimeStr || '-';
|
||||
}
|
||||
"
|
||||
/>
|
||||
<a-col :span="8">
|
||||
<a-tooltip :title="formatDuration(item.upTimeStr) || '-'">
|
||||
<a-statistic
|
||||
title="运行时间"
|
||||
valueStyle="font-size: 14px;overflow: hidden; text-overflow: ellipsis; white-space: nowrap"
|
||||
:formatter="
|
||||
(v) => {
|
||||
return formatDuration(item.upTimeStr, '', 1) || '-';
|
||||
}
|
||||
"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-tooltip :title="`${item.status === 4 ? '-' : parseTime(item.modifyTimeMillis)}`">
|
||||
<a-statistic
|
||||
title="更新时间"
|
||||
valueStyle="font-size: 14px;overflow: hidden; text-overflow: ellipsis; white-space: nowrap"
|
||||
:formatter="
|
||||
(v) => {
|
||||
return item.status === 4 ? '-' : parseTime(item.modifyTimeMillis, '{h}:{i}:{s}');
|
||||
}
|
||||
"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
@ -177,7 +214,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { getStatist, status, statusStat } from "@/api/node-stat";
|
||||
import { parseTime } from "@/utils/time";
|
||||
import { parseTime, formatDuration } from "@/utils/time";
|
||||
import { PAGE_DEFAULT_SHOW_TOTAL, PAGE_DEFAULT_LIST_QUERY } from "@/utils/const";
|
||||
import NodeTop from "@/pages/node/node-layout/node-top";
|
||||
|
||||
@ -212,7 +249,8 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
PAGE_DEFAULT_SHOW_TOTAL,
|
||||
|
||||
parseTime,
|
||||
formatDuration,
|
||||
// 加载数据
|
||||
loadData(pointerEvent) {
|
||||
//this.list = [];
|
||||
@ -244,7 +282,7 @@ export default {
|
||||
onFinish() {
|
||||
this.loadData();
|
||||
},
|
||||
parseTime,
|
||||
|
||||
// 历史图表
|
||||
handleHistory(record, type) {
|
||||
this.monitorVisible = true;
|
||||
|
@ -251,7 +251,24 @@
|
||||
bordered
|
||||
:rowKey="(record, index) => index"
|
||||
>
|
||||
<a-tooltip slot="commands" slot-scope="text" placement="topLeft" :title="text">
|
||||
<a-tooltip
|
||||
slot="commands"
|
||||
slot-scope="text"
|
||||
placement="topLeft"
|
||||
:title="text"
|
||||
v-clipboard:copy="text"
|
||||
v-clipboard:success="
|
||||
() => {
|
||||
tempVue.prototype.$notification.success({ message: '复制成功' });
|
||||
}
|
||||
"
|
||||
v-clipboard:error="
|
||||
() => {
|
||||
tempVue.prototype.$notification.error({ message: '复制失败' });
|
||||
}
|
||||
"
|
||||
>
|
||||
<a-icon type="copy" />
|
||||
<span>{{ text }}</span>
|
||||
</a-tooltip>
|
||||
<a-tooltip slot="modifyUser" slot-scope="text, item" placement="topLeft" :title="item.modifyUser || item.userId">
|
||||
@ -261,9 +278,9 @@
|
||||
<a-tooltip slot="userAgent" slot-scope="text" placement="topLeft" :title="text">
|
||||
<span>{{ text }}</span>
|
||||
</a-tooltip>
|
||||
<a-tooltip slot="refuse" slot-scope="text" placement="topLeft" :title="text">
|
||||
<template slot="refuse" slot-scope="text">
|
||||
<span>{{ text ? "成功" : "拒绝" }}</span>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
</div>
|
||||
@ -274,6 +291,7 @@ import SshFile from "@/pages/ssh/ssh-file";
|
||||
import Terminal from "@/pages/ssh/terminal";
|
||||
import { parseTime } from "@/utils/time";
|
||||
import { PAGE_DEFAULT_LIMIT, PAGE_DEFAULT_SIZW_OPTIONS, PAGE_DEFAULT_SHOW_TOTAL, PAGE_DEFAULT_LIST_QUERY } from "@/utils/const";
|
||||
import Vue from "vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -312,6 +330,7 @@ export default {
|
||||
title: "执行命令",
|
||||
dataIndex: "commands",
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: "commands" },
|
||||
},
|
||||
{
|
||||
@ -337,12 +356,8 @@ export default {
|
||||
} /*width: 180*/,
|
||||
},
|
||||
],
|
||||
viewOperationLogTotal: 0,
|
||||
viewOperationLogListQuery: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
},
|
||||
|
||||
viewOperationLogListQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
||||
columns: [
|
||||
{ title: "名称", dataIndex: "name", sorter: true, ellipsis: true },
|
||||
|
||||
@ -400,6 +415,7 @@ export default {
|
||||
url: [{ required: true, message: "Please input url", trigger: "blur" }],
|
||||
path: [{ required: true, message: "Please input path", trigger: "blur" }],
|
||||
},
|
||||
tempVue: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -511,6 +527,10 @@ export default {
|
||||
this.temp = Object.assign(record);
|
||||
this.viewOperationLogListQuery.sshId = this.temp.id;
|
||||
this.viewOperationLog = true;
|
||||
this.viewOperationLogList = [];
|
||||
this.viewOperationLogListQuery.total = 0;
|
||||
this.viewOperationLogListQuery.page = 1;
|
||||
this.tempVue = Vue;
|
||||
this.handleListLog();
|
||||
},
|
||||
handleListLog() {
|
||||
|
@ -181,12 +181,16 @@ export default {
|
||||
});
|
||||
},
|
||||
initWebsocket(ids) {
|
||||
if (!this.socket || this.socket.readyState !== this.socket.OPEN || this.socket.readyState !== this.socket.CONNECTING) {
|
||||
this.socket = new WebSocket(this.socketUrl);
|
||||
if (this.socket) {
|
||||
this.initHeart(ids);
|
||||
return;
|
||||
}
|
||||
// if (!this.socket || this.socket.readyState !== this.socket.OPEN || this.socket.readyState !== this.socket.CONNECTING) {
|
||||
this.socket = new WebSocket(this.socketUrl);
|
||||
// }
|
||||
|
||||
this.socket.onopen = () => {
|
||||
this.init(ids);
|
||||
this.initHeart(ids);
|
||||
};
|
||||
this.socket.onmessage = ({ data: socketData }) => {
|
||||
let msgObj;
|
||||
@ -231,7 +235,7 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
init(ids) {
|
||||
initHeart(ids) {
|
||||
this.sendMsg("getNodeList:" + ids.join(","));
|
||||
this.getAgentVersion();
|
||||
// 创建心跳,防止掉线
|
||||
@ -241,11 +245,11 @@ export default {
|
||||
}, 2000);
|
||||
},
|
||||
refresh() {
|
||||
if (this.socket) {
|
||||
this.socket.close();
|
||||
}
|
||||
this.nodeStatus = {};
|
||||
this.nodeVersion = {};
|
||||
// if (this.socket) {
|
||||
// this.socket.close();
|
||||
// }
|
||||
//this.nodeStatus = {};
|
||||
//this.nodeVersion = {};
|
||||
this.getNodeList();
|
||||
},
|
||||
batchUpdate() {
|
||||
|
@ -84,3 +84,31 @@ export function itemGroupBy(arr, groupKey, key, dataKey) {
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时长
|
||||
* @param {String} ms
|
||||
* @param {String} seg 分割符
|
||||
* @param {String} levelCount 格式化个数
|
||||
* @returns
|
||||
*/
|
||||
export function formatDuration(ms, seg, levelCount) {
|
||||
if (isNaN(new Number(ms))) {
|
||||
return ms;
|
||||
}
|
||||
seg = seg || "";
|
||||
levelCount = levelCount || 5;
|
||||
if (ms < 0) ms = -ms;
|
||||
const time = {
|
||||
天: Math.floor(ms / 86400000),
|
||||
小时: Math.floor(ms / 3600000) % 24,
|
||||
分钟: Math.floor(ms / 60000) % 60,
|
||||
秒: Math.floor(ms / 1000) % 60,
|
||||
毫秒: Math.floor(ms) % 1000,
|
||||
};
|
||||
return Object.entries(time)
|
||||
.filter((val) => val[1] !== 0)
|
||||
.map(([key, val]) => `${val}${key}`)
|
||||
.splice(0, levelCount)
|
||||
.join(seg);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user