新增查看页面
This commit is contained in:
@@ -29,7 +29,7 @@
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.16</version>
|
||||
<version>5.8.42</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,7 +41,19 @@
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
<artifactId>commons-net</artifactId>
|
||||
<version>3.11.0</version> <!-- 请根据需要使用最新版本 -->
|
||||
<version>3.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>5.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Commons -->
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.jeesite.modules.app.Job.biz;
|
||||
|
||||
import com.jcraft.jsch.Session;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.modules.app.dao.info.CpuInfo;
|
||||
import com.jeesite.modules.app.dao.info.DiskInfo;
|
||||
@@ -81,41 +82,46 @@ public class hostJob {
|
||||
public void syncServerInfo(BizMonitorHost host) {
|
||||
BizMonitorAccount monitorAccount = new BizMonitorAccount();
|
||||
monitorAccount.setHostId(host.getHostId());
|
||||
monitorAccount.setUstatus("1");
|
||||
monitorAccount.setSshUsername("ogsapp");
|
||||
List<BizMonitorAccount> accountList = accountService.findList(monitorAccount);
|
||||
if (accountList.size() > 0) {
|
||||
try {
|
||||
BizMonitorAccount account = accountList.get(0);
|
||||
CpuInfo cpuInfo = SystemUtil.getCpuMemUsage(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), vo.getDecode(account.getSshPassword()));
|
||||
ServerInfo info = SystemUtil.getServerBasicInfo(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), vo.getDecode(account.getSshPassword()), host.getIpAddress());
|
||||
List<DiskInfo> diskInfos = SystemUtil.getDiskInfos(host.getIpAddress(), account.getSshPort(), account.getSshUsername(), vo.getDecode(account.getSshPassword()));
|
||||
syncDeviceInfo(host, diskInfos);
|
||||
BizServerInfo bizServerInfo = new BizServerInfo();
|
||||
bizServerInfo.setHostId(host.getHostId());
|
||||
List<BizServerInfo> serverInfoList = serverInfoService.findList(bizServerInfo);
|
||||
BizServerInfo serverInfo = serverInfoList.isEmpty() ? new BizServerInfo() : serverInfoList.get(0);
|
||||
serverInfo.setUptime(info.getUptime());
|
||||
serverInfo.setOs(info.getOs());
|
||||
serverInfo.setKernelVersion(info.getKernelVersion());
|
||||
serverInfo.setHostname(info.getHostname());
|
||||
serverInfo.setIpAddress(info.getIpAddress());
|
||||
serverInfo.setCpuModel(info.getCpuModel());
|
||||
serverInfo.setMemoryTotal(info.getMemoryTotal());
|
||||
serverInfo.setCpuUsage(cpuInfo.getCpuUsage());
|
||||
serverInfo.setMemoryUsage(cpuInfo.getMemoryUsage());
|
||||
serverInfo.setLastOnlineTime(new Date());
|
||||
serverInfo.setHostId(host.getHostId());
|
||||
serverInfoService.save(serverInfo);
|
||||
if (serverInfo.getCpuUsage() >= CPU_RATE) {
|
||||
BizWarningAlert warningAlert = new BizWarningAlert("ZJ_" + KeyUtil.ObjKey(12, 2), "CPU预警", 2, serverInfo.getHostname() + "CPU预警", "当前主机CPU已超过" + CPU_RATE + "%,请及时处理,主机IP:" + serverInfo.getIpAddress(), "业务系统", "0");
|
||||
bizWarningAlertService.save(warningAlert);
|
||||
}
|
||||
if (serverInfo.getMemoryUsage() >= MEM_RATE) {
|
||||
BizWarningAlert warningAlert = new BizWarningAlert("ZJ_" + KeyUtil.ObjKey(12, 2), "内存预警", 2, serverInfo.getHostname() + "内存预警", "当前主机内存已超过" + MEM_RATE + "%,请及时处理,主机IP:" + serverInfo.getIpAddress(), "业务系统", "0");
|
||||
bizWarningAlertService.save(warningAlert);
|
||||
Session session = SystemUtil.getSshSession(account);
|
||||
if (session.isConnected()) {
|
||||
CpuInfo cpuInfo = SystemUtil.getCpuMemUsage(session);
|
||||
ServerInfo info = SystemUtil.getServerBasicInfo(session);
|
||||
List<DiskInfo> diskInfos = SystemUtil.getDiskInfos(session);
|
||||
syncDeviceInfo(host, diskInfos);
|
||||
BizServerInfo bizServerInfo = new BizServerInfo();
|
||||
bizServerInfo.setHostId(host.getHostId());
|
||||
List<BizServerInfo> serverInfoList = serverInfoService.findList(bizServerInfo);
|
||||
BizServerInfo serverInfo = serverInfoList.isEmpty() ? new BizServerInfo() : serverInfoList.get(0);
|
||||
serverInfo.setUptime(info.getUptime());
|
||||
serverInfo.setOs(info.getOs());
|
||||
serverInfo.setKernelVersion(info.getKernelVersion());
|
||||
serverInfo.setHostname(info.getHostname());
|
||||
serverInfo.setIpAddress(info.getIpAddress());
|
||||
serverInfo.setCpuModel(info.getCpuModel());
|
||||
serverInfo.setMemoryTotal(info.getMemoryTotal());
|
||||
serverInfo.setCpuUsage(cpuInfo.getCpuUsage());
|
||||
serverInfo.setMemoryUsage(cpuInfo.getMemoryUsage());
|
||||
serverInfo.setLastOnlineTime(new Date());
|
||||
serverInfo.setHostId(host.getHostId());
|
||||
serverInfoService.save(serverInfo);
|
||||
if (serverInfo.getCpuUsage() >= CPU_RATE) {
|
||||
BizWarningAlert warningAlert = new BizWarningAlert("ZJ_" + KeyUtil.ObjKey(12, 2), "CPU预警", 2, serverInfo.getHostname() + "CPU预警", "当前主机CPU已超过" + CPU_RATE + "%,请及时处理,主机IP:" + serverInfo.getIpAddress(), "业务系统", "0");
|
||||
bizWarningAlertService.save(warningAlert);
|
||||
}
|
||||
if (serverInfo.getMemoryUsage() >= MEM_RATE) {
|
||||
BizWarningAlert warningAlert = new BizWarningAlert("ZJ_" + KeyUtil.ObjKey(12, 2), "内存预警", 2, serverInfo.getHostname() + "内存预警", "当前主机内存已超过" + MEM_RATE + "%,请及时处理,主机IP:" + serverInfo.getIpAddress(), "业务系统", "0");
|
||||
bizWarningAlertService.save(warningAlert);
|
||||
}
|
||||
SystemUtil.closeSession(session);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
logger.error(e.getMessage(), host);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,7 +151,7 @@ public class hostJob {
|
||||
bizWarningAlertService.save(warningAlert);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
logger.error(e.getMessage(), host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
package com.jeesite.modules.app;
|
||||
|
||||
import com.jeesite.modules.app.utils.SystemUtil;
|
||||
|
||||
import com.jcraft.jsch.Session;
|
||||
|
||||
public class Test {
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
|
||||
// Session session = SystemUtil.getSshSession("192.168.31.182", 22, "ogsapp", "WIjYVp3bSNaJ7gK9n9jk7Q==");
|
||||
//
|
||||
// System.out.println(SystemUtil.getServerBasicInfo(session));
|
||||
}
|
||||
}
|
||||
|
||||
109
web-api/src/main/java/com/jeesite/modules/app/utils/AesUtil.java
Normal file
109
web-api/src/main/java/com/jeesite/modules/app/utils/AesUtil.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package com.jeesite.modules.app.utils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* AES加密解密工具类(CBC/PKCS5Padding)
|
||||
* 优化说明:修复密钥BUG+解决换行问题+性能优化+安全加固+零依赖
|
||||
*/
|
||||
public class AesUtil {
|
||||
|
||||
|
||||
private static final LoggerUtils logger = LoggerUtils.getInstance();
|
||||
private static final String AES_KEY_HEX = "AD42F6697B035B7580E4FEF93BE20BAD"; // 你的32位16进制密钥
|
||||
private static final String CHARSET = StandardCharsets.UTF_8.name();
|
||||
private static final int IV_LENGTH = 16; // AES CBC IV固定16字节
|
||||
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
|
||||
private static final String ALGORITHM = "AES";
|
||||
|
||||
private static final ThreadLocal<Cipher> ENCRYPT_CIPHER = ThreadLocal.withInitial(() -> {
|
||||
try {
|
||||
return Cipher.getInstance(TRANSFORMATION);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
private static final ThreadLocal<Cipher> DECRYPT_CIPHER = ThreadLocal.withInitial(() -> {
|
||||
try {
|
||||
return Cipher.getInstance(TRANSFORMATION);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*/
|
||||
public static String encrypt(String content) {
|
||||
return encrypt(content, hex2Bytes(AES_KEY_HEX));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*/
|
||||
public static String decrypt(String content) {
|
||||
return decrypt(content, hex2Bytes(AES_KEY_HEX));
|
||||
}
|
||||
|
||||
public static String encrypt(String content, byte[] key) {
|
||||
if (content == null || content.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
|
||||
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(key, IV_LENGTH));
|
||||
Cipher cipher = ENCRYPT_CIPHER.get();
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
|
||||
byte[] encryptBytes = cipher.doFinal(content.getBytes(CHARSET));
|
||||
return Base64.getEncoder().encodeToString(encryptBytes);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String decrypt(String content, byte[] key) {
|
||||
if (content == null || content.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
|
||||
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(key, IV_LENGTH));
|
||||
Cipher cipher = DECRYPT_CIPHER.get();
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
|
||||
byte[] decryptBytes = cipher.doFinal(Base64.getDecoder().decode(content));
|
||||
String result = new String(decryptBytes, CHARSET);
|
||||
return result.trim();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 32位16进制字符串转16字节数组(解决你的密钥长度BUG的核心方法)
|
||||
*/
|
||||
private static byte[] hex2Bytes(String hexStr) {
|
||||
if (hexStr == null || hexStr.length() % 2 != 0) {
|
||||
throw new IllegalArgumentException("密钥必须是偶数长度的16进制字符串");
|
||||
}
|
||||
byte[] bytes = new byte[hexStr.length() / 2];
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = (byte) Integer.parseInt(hexStr.substring(i * 2, i * 2 + 2), 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机16字节IV向量(方案2:安全随机IV,新业务推荐使用)
|
||||
*/
|
||||
private static byte[] generateRandomIV() {
|
||||
byte[] iv = new byte[IV_LENGTH];
|
||||
ThreadLocalRandom.current().nextBytes(iv);
|
||||
return iv;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.jeesite.modules.app.utils;
|
||||
|
||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
@@ -19,6 +19,10 @@ public class MyUtils {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getPath(String... paths) {
|
||||
return String.join("/", paths);
|
||||
}
|
||||
|
||||
|
||||
public static Map<String, Object> convertToTreeNode(BizFolders folder, String parentName) {
|
||||
Map<String, Object> node = new HashMap<>();
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.jeesite.modules.app.utils;
|
||||
|
||||
|
||||
import com.jcraft.jsch.ChannelExec;
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.Session;
|
||||
import com.jeesite.modules.app.dao.info.CpuInfo;
|
||||
import com.jeesite.modules.app.dao.info.DiskInfo;
|
||||
import com.jeesite.modules.app.dao.info.ServerInfo;
|
||||
import com.jeesite.modules.biz.entity.BizMonitorAccount;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -15,165 +15,193 @@ import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* 服务器系统信息采集工具类(SSH方式)
|
||||
* 最终优化版:解决Session复用问题,调用方统一管理会话生命周期,杜绝重复关闭
|
||||
*/
|
||||
public class SystemUtil {
|
||||
|
||||
|
||||
// SSH 连接超时时间(毫秒)
|
||||
private static final int SSH_TIMEOUT = 5000;
|
||||
|
||||
// CPU使用率默认值
|
||||
private static final double DEFAULT_USAGE = 0.0;
|
||||
private static final List<String> FILTER_FILE_SYSTEM = Arrays.asList("dev");
|
||||
|
||||
/**
|
||||
* 建立SSH连接
|
||||
*/
|
||||
private static Session getSshSession(String host, int port, String username, String password) throws Exception {
|
||||
JSch jsch = new JSch();
|
||||
Session session = jsch.getSession(username, host, port);
|
||||
session.setPassword(password);
|
||||
|
||||
Properties config = new Properties();
|
||||
config.put("StrictHostKeyChecking", "no");
|
||||
session.setConfig(config);
|
||||
|
||||
session.setTimeout(SSH_TIMEOUT);
|
||||
session.connect();
|
||||
public static Session getSshSession(BizMonitorAccount account) {
|
||||
Session session = null;
|
||||
try {
|
||||
String passwd = AesUtil.decrypt(account.getSshPassword());
|
||||
JSch jsch = new JSch();
|
||||
session = jsch.getSession(account.getSshUsername(), account.getIpAddress(), account.getSshPort());
|
||||
session.setPassword(passwd);
|
||||
Properties config = new Properties();
|
||||
config.put("StrictHostKeyChecking", "no");
|
||||
session.setConfig(config);
|
||||
session.setTimeout(account.getTimeoutSeconds());
|
||||
session.connect();
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
// ======================== 统一的资源关闭工具方法 ========================
|
||||
|
||||
/**
|
||||
* 执行SSH命令并返回结果
|
||||
* 安全关闭SSH通道,空指针安全+异常捕获
|
||||
*/
|
||||
private static String executeCommand(Session session, String command) throws Exception {
|
||||
ChannelExec channel = (ChannelExec) session.openChannel("exec");
|
||||
channel.setCommand(command);
|
||||
|
||||
InputStream in = channel.getInputStream();
|
||||
channel.connect();
|
||||
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(in, StandardCharsets.UTF_8)
|
||||
);
|
||||
StringBuilder result = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
result.append(line).append("\n");
|
||||
private static void closeChannel(ChannelExec channel) {
|
||||
if (channel != null && channel.isConnected()) {
|
||||
try {
|
||||
channel.disconnect();
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
reader.close();
|
||||
channel.disconnect();
|
||||
return result.toString().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全关闭SSH会话,空指针安全+异常捕获
|
||||
* 【核心】仅提供给调用方,在所有业务查询完成后统一调用!
|
||||
*/
|
||||
public static void closeSession(Session session) {
|
||||
if (session != null && session.isConnected()) {
|
||||
try {
|
||||
session.disconnect();
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行SSH命令并返回结果(核心优化,资源闭环+异常安全)
|
||||
*/
|
||||
private static String executeCommand(Session session, String command) throws Exception {
|
||||
if (session == null || !session.isConnected() || !StringUtils.hasText(command)) {
|
||||
return "";
|
||||
}
|
||||
ChannelExec channel = null;
|
||||
try {
|
||||
channel = (ChannelExec) session.openChannel("exec");
|
||||
channel.setCommand(command);
|
||||
try (InputStream in = channel.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
|
||||
channel.connect();
|
||||
StringBuilder result = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
result.append(line).append("\n");
|
||||
}
|
||||
return result.toString().trim();
|
||||
}
|
||||
} finally {
|
||||
// 只关闭通道,不关闭会话
|
||||
closeChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务器基础信息
|
||||
* ✅ 关键修改:移除finally中的closeSession(session),不再关闭会话
|
||||
*/
|
||||
public static ServerInfo getServerBasicInfo(String host, int port, String username, String password, String ipAddress) throws Exception {
|
||||
public static ServerInfo getServerBasicInfo(Session session) {
|
||||
ServerInfo info = new ServerInfo();
|
||||
Session session = null;
|
||||
try {
|
||||
session = getSshSession(host, port, username, password);
|
||||
|
||||
// 主机运行时间
|
||||
String uptimeResult = executeCommand(session, "uptime");
|
||||
if (StringUtils.hasText(uptimeResult)) {
|
||||
String[] parts = uptimeResult.split("up ");
|
||||
if (parts.length > 1) {
|
||||
info.setUptime(parts[1].split(", ")[0]);
|
||||
String uptime = parts[1].split(",")[0];
|
||||
info.setUptime(uptime);
|
||||
}
|
||||
}
|
||||
|
||||
// 操作系统
|
||||
String osResult = executeCommand(session, "cat /etc/os-release | grep PRETTY_NAME | cut -d'=' -f2 | tr -d '\"'");
|
||||
info.setOs(osResult.isEmpty() ? "Unknown" : osResult);
|
||||
|
||||
info.setOs(StringUtils.hasText(osResult) ? osResult : "Unknown");
|
||||
// 内核版本
|
||||
info.setKernelVersion(executeCommand(session, "uname -r"));
|
||||
|
||||
// 主机名
|
||||
info.setHostname(executeCommand(session, "hostname"));
|
||||
|
||||
// IP地址(传入参数)
|
||||
info.setIpAddress(ipAddress);
|
||||
|
||||
info.setIpAddress(session.getHost());
|
||||
// CPU型号
|
||||
String cpuResult = executeCommand(session, "cat /proc/cpuinfo | grep 'model name' | head -n 1 | cut -d: -f2 | sed -e 's/^ *//'");
|
||||
info.setCpuModel(cpuResult.isEmpty() ? "Unknown" : cpuResult);
|
||||
|
||||
info.setCpuModel(StringUtils.hasText(cpuResult) ? cpuResult : "Unknown");
|
||||
// 内存总量
|
||||
String memResult = executeCommand(session, "free -h | grep Mem | awk '{print $2}'");
|
||||
info.setMemoryTotal(memResult.isEmpty() ? "Unknown" : memResult);
|
||||
|
||||
} finally {
|
||||
if (session != null && session.isConnected()) {
|
||||
session.disconnect();
|
||||
}
|
||||
info.setMemoryTotal(StringUtils.hasText(memResult) ? memResult : "Unknown");
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取CPU和内存使用率
|
||||
* ✅ 关键修改:移除finally中的closeSession(session),不再关闭会话
|
||||
*/
|
||||
public static CpuInfo getCpuMemUsage(String host, int port, String username, String password) throws Exception {
|
||||
public static CpuInfo getCpuMemUsage(Session session) {
|
||||
CpuInfo usage = new CpuInfo();
|
||||
Session session = null;
|
||||
try {
|
||||
session = getSshSession(host, port, username, password);
|
||||
|
||||
// CPU使用率
|
||||
String cpuCommand = "top -bn2 | grep '%Cpu' | tail -n1 | awk '{print 100 - $8}'";
|
||||
String cpuResult = executeCommand(session, cpuCommand);
|
||||
if (StringUtils.hasText(cpuResult)) {
|
||||
usage.setCpuUsage(Double.parseDouble(cpuResult));
|
||||
} else {
|
||||
usage.setCpuUsage(DEFAULT_USAGE);
|
||||
}
|
||||
// 内存使用率
|
||||
String memCommand = "free | grep Mem | awk '{print $3/$2 * 100}'";
|
||||
String memResult = executeCommand(session, memCommand);
|
||||
if (StringUtils.hasText(memResult)) {
|
||||
usage.setMemoryUsage(Double.parseDouble(memResult));
|
||||
} else {
|
||||
usage.setMemoryUsage(DEFAULT_USAGE);
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (session != null && session.isConnected()) {
|
||||
session.disconnect();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有磁盘信息
|
||||
* ✅ 关键修改:移除finally中的closeSession(session),不再关闭会话
|
||||
*/
|
||||
public static List<DiskInfo> getDiskInfos(String host, int port, String username, String password) throws Exception {
|
||||
public static List<DiskInfo> getDiskInfos(Session session) {
|
||||
List<DiskInfo> diskInfos = new ArrayList<>();
|
||||
Session session = null;
|
||||
try {
|
||||
session = getSshSession(host, port, username, password);
|
||||
// 关键修改:强制英文输出 + 调整字段索引
|
||||
String diskCommand = "LANG=en_US.UTF-8 df -h | awk '{print $1, $6, $2, $3, $5}'";
|
||||
String diskResult = executeCommand(session, diskCommand);
|
||||
|
||||
if (StringUtils.hasText(diskResult)) {
|
||||
String[] lines = diskResult.split("\n");
|
||||
for (String line : lines) {
|
||||
// 过滤空行和标题行
|
||||
if (line.trim().isEmpty() || line.contains("Filesystem")) {
|
||||
continue;
|
||||
}
|
||||
// 按任意空格分割(兼容多个空格)
|
||||
String[] parts = line.trim().split("\\s+");
|
||||
if (parts.length >= 5) {
|
||||
String fileSystem = parts[0];
|
||||
boolean isFilter = FILTER_FILE_SYSTEM.stream().anyMatch(fileSystem::contains);
|
||||
if (isFilter) {
|
||||
continue;
|
||||
}
|
||||
double usage = DEFAULT_USAGE;
|
||||
String usageStr = parts[4].replace("%", "").trim();
|
||||
DiskInfo diskInfo = new DiskInfo(parts[0], parts[1], parts[2], parts[3], Double.parseDouble(usageStr));
|
||||
if (StringUtils.hasText(usageStr)) {
|
||||
usage = Double.parseDouble(usageStr);
|
||||
}
|
||||
DiskInfo diskInfo = new DiskInfo(parts[0], parts[1], parts[2], parts[3], usage);
|
||||
diskInfos.add(diskInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (session != null && session.isConnected()) {
|
||||
session.disconnect();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
return diskInfos;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.jeesite.modules.app.utils;
|
||||
|
||||
|
||||
import com.jcraft.jsch.ChannelSftp;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.extra.ssh.JschUtil;
|
||||
import cn.hutool.extra.ssh.Sftp;
|
||||
import com.jeesite.modules.biz.entity.BizMonitorAccount;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class sftpUtils {
|
||||
|
||||
private static final LoggerUtils logger = LoggerUtils.getInstance();
|
||||
|
||||
|
||||
public static Filter<ChannelSftp.LsEntry> ruleFilter(String pattern) {
|
||||
if (pattern == null || pattern.isBlank()) {
|
||||
return entry -> false;
|
||||
}
|
||||
String matchPattern = pattern.trim().toLowerCase();
|
||||
String[] ruleArr = matchPattern.split(",");
|
||||
StringBuilder regexBuilder = new StringBuilder();
|
||||
for (int i = 0; i < ruleArr.length; i++) {
|
||||
String rule = ruleArr[i].trim();
|
||||
if (rule.isBlank()) continue;
|
||||
// 通配符转正则
|
||||
String singleRegex = rule.replace(".", "\\.").replace("*", ".*");
|
||||
regexBuilder.append("^").append(singleRegex).append("$");
|
||||
if (i < ruleArr.length - 1) {
|
||||
regexBuilder.append("|"); // 多规则用或连接
|
||||
}
|
||||
}
|
||||
Pattern compilePattern = Pattern.compile(regexBuilder.toString());
|
||||
return entry -> {
|
||||
if (entry == null || entry.getAttrs().isDir()) {
|
||||
return false;
|
||||
}
|
||||
String fileName = entry.getFilename();
|
||||
if (fileName == null || fileName.isBlank()) {
|
||||
return false;
|
||||
}
|
||||
return compilePattern.matcher(fileName.toLowerCase()).matches();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
public static void fileUpload(BizMonitorAccount account, String getRemotePath, String localFile) {
|
||||
try {
|
||||
File file = new File(localFile);
|
||||
if (file.exists()) {
|
||||
Sftp sftp = JschUtil.createSftp(account.getIpAddress(), account.getSshPort(), account.getSshUsername(), AesUtil.decrypt(account.getSshPassword()));
|
||||
sftp.put(localFile, getRemotePath);
|
||||
sftp.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*/
|
||||
public static void fileDownload(BizMonitorAccount account, String getRemotePath, String filter, String localPath) {
|
||||
try {
|
||||
Sftp sftp = JschUtil.createSftp(account.getIpAddress(), account.getSshPort(), account.getSshUsername(), AesUtil.decrypt(account.getSshPassword()));
|
||||
List<String> files = sftp.ls(getRemotePath, ruleFilter(filter));
|
||||
for (String fileName : files) {
|
||||
sftp.get(MyUtils.getPath(getRemotePath, fileName), localPath);
|
||||
}
|
||||
sftp.close();
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.jeesite.modules.app.utils;
|
||||
|
||||
import com.jeesite.common.codec.AesUtils;
|
||||
|
||||
|
||||
public class vo {
|
||||
|
||||
private static final String AES_KEY = "010e06108bb801e85f8738e01c396dd2";
|
||||
|
||||
/**
|
||||
* 获取加密Key
|
||||
*/
|
||||
public static String getKey() {
|
||||
return AesUtils.genKeyString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*/
|
||||
public static String getEncode(String s) {
|
||||
try {
|
||||
return AesUtils.encode(s, AES_KEY);
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*/
|
||||
public static String getDecode(String s) {
|
||||
try {
|
||||
return AesUtils.decode(s, AES_KEY);
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.jeesite.modules.biz.web;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.jeesite.modules.app.utils.vo;
|
||||
import com.jeesite.modules.app.utils.AesUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -91,11 +90,11 @@ public class BizMonitorAccountController extends BaseController {
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMonitorAccount bizMonitorAccount) {
|
||||
if (bizMonitorAccount.getIsNewRecord()) {
|
||||
bizMonitorAccount.setSshPassword(vo.getEncode(bizMonitorAccount.getSshPassword()));
|
||||
bizMonitorAccount.setSshPassword(AesUtil.encrypt(bizMonitorAccount.getSshPassword()));
|
||||
} else {
|
||||
BizMonitorAccount account = bizMonitorAccountService.get(bizMonitorAccount.getAccountId());
|
||||
if (!account.getSshPassword().equals(bizMonitorAccount.getSshPassword())) {
|
||||
bizMonitorAccount.setSshPassword(vo.getEncode(bizMonitorAccount.getSshPassword()));
|
||||
bizMonitorAccount.setSshPassword(AesUtil.encrypt(bizMonitorAccount.getSshPassword()));
|
||||
}
|
||||
}
|
||||
bizMonitorAccountService.save(bizMonitorAccount);
|
||||
|
||||
Reference in New Issue
Block a user