增加主机信息功能
This commit is contained in:
@@ -32,9 +32,4 @@ public class SftpResult implements Serializable {
|
|||||||
public boolean isSuccess() { return success; }
|
public boolean isSuccess() { return success; }
|
||||||
public String getMessage() { return message; }
|
public String getMessage() { return message; }
|
||||||
public Object getData() { return data; }
|
public Object getData() { return data; }
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "SftpResult{success=" + success + ", message='" + message + "'}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,17 +204,4 @@ public class MonitorUtil {
|
|||||||
}
|
}
|
||||||
return out.toString(StandardCharsets.UTF_8);
|
return out.toString(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
MySftpAccounts sftpAccounts = new MySftpAccounts();
|
|
||||||
sftpAccounts.setHostIp("192.168.31.194");
|
|
||||||
sftpAccounts.setHostPort(22);
|
|
||||||
sftpAccounts.setUsername("ogsapp");
|
|
||||||
sftpAccounts.setPassword("Sys@2026#me");
|
|
||||||
sftpAccounts.setRootPath("/ogsapp");
|
|
||||||
sftpAccounts.setAuthType("password");
|
|
||||||
SftpResult sftpResult = MonitorUtil.monitor(sftpAccounts);
|
|
||||||
System.out.println(sftpResult.getData());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,187 +299,6 @@ public class SftpUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------ 系统监控
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取远程主机系统信息:CPU、内存、磁盘、负载、在线时长
|
|
||||||
* 通过 SSH exec 执行系统命令采集
|
|
||||||
*
|
|
||||||
* @param account SSH账号
|
|
||||||
* @return SftpResult,data 为 Map 结构
|
|
||||||
*/
|
|
||||||
public static SftpResult systemInfo(MySftpAccounts account) {
|
|
||||||
Session session = null;
|
|
||||||
ChannelExec exec = null;
|
|
||||||
try {
|
|
||||||
session = openSession(account);
|
|
||||||
exec = (ChannelExec) session.openChannel("exec");
|
|
||||||
// 一次性采集所有指标
|
|
||||||
exec.setCommand(
|
|
||||||
"echo '===HOSTNAME===' && hostname && " +
|
|
||||||
"echo '===UPTIME===' && uptime -p 2>/dev/null || uptime && " +
|
|
||||||
"echo '===CPU===' && top -bn1 | head -5 && " +
|
|
||||||
"echo '===MEM===' && free -m && " +
|
|
||||||
"echo '===DISK===' && df -h"
|
|
||||||
);
|
|
||||||
InputStream in = exec.getInputStream();
|
|
||||||
InputStream errIn = exec.getErrStream();
|
|
||||||
exec.connect(SSH_TIMEOUT);
|
|
||||||
|
|
||||||
String output = readStream(in);
|
|
||||||
String err = readStream(errIn);
|
|
||||||
if (!err.isEmpty() && output.isEmpty()) {
|
|
||||||
return SftpResult.fail("采集失败: " + err);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> info = new LinkedHashMap<>();
|
|
||||||
info.put("hostname", extract(output, "HOSTNAME", true));
|
|
||||||
info.put("uptime", extract(output, "UPTIME", true));
|
|
||||||
info.put("cpu", parseCpu(extract(output, "CPU", false)));
|
|
||||||
info.put("memory", parseMemory(extract(output, "MEM", false)));
|
|
||||||
info.put("disk", parseDisk(extract(output, "DISK", false)));
|
|
||||||
return SftpResult.ok("采集成功", info);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return SftpResult.fail("采集失败: " + e.getMessage());
|
|
||||||
} finally {
|
|
||||||
if (exec != null && exec.isConnected()) exec.disconnect();
|
|
||||||
if (session != null && session.isConnected()) session.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- session 工具 ----
|
|
||||||
|
|
||||||
private static Session openSession(MySftpAccounts account) throws JSchException {
|
|
||||||
JSch jsch = new JSch();
|
|
||||||
int port = Optional.ofNullable(account.getHostPort()).orElse(22);
|
|
||||||
if ("key".equalsIgnoreCase(account.getAuthType())
|
|
||||||
&& StringUtils.isNotBlank(account.getPrivateKey())) {
|
|
||||||
jsch.addIdentity("tempKey",
|
|
||||||
account.getPrivateKey().getBytes(StandardCharsets.UTF_8),
|
|
||||||
null, null);
|
|
||||||
}
|
|
||||||
Session session = jsch.getSession(account.getUsername(), account.getHostIp(), port);
|
|
||||||
session.setTimeout(SSH_TIMEOUT);
|
|
||||||
if (!"key".equalsIgnoreCase(account.getAuthType())) {
|
|
||||||
session.setPassword(account.getPassword());
|
|
||||||
}
|
|
||||||
Properties config = new Properties();
|
|
||||||
config.put("StrictHostKeyChecking", "no");
|
|
||||||
session.setConfig(config);
|
|
||||||
session.connect(SSH_TIMEOUT);
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String readStream(InputStream in) throws IOException {
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
byte[] buf = new byte[4096];
|
|
||||||
int len;
|
|
||||||
while ((len = in.read(buf)) != -1) {
|
|
||||||
out.write(buf, 0, len);
|
|
||||||
}
|
|
||||||
return out.toString(StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- 解析工具 ----
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 按 ===MARK=== 分割提取段落
|
|
||||||
*/
|
|
||||||
private static String extract(String output, String mark, boolean singleLine) {
|
|
||||||
String start = "===" + mark + "===";
|
|
||||||
int s = output.indexOf(start);
|
|
||||||
if (s < 0) return "";
|
|
||||||
s += start.length();
|
|
||||||
if (s >= output.length()) return "";
|
|
||||||
// 跳过紧跟的换行
|
|
||||||
if (output.charAt(s) == '\n') s++;
|
|
||||||
if (singleLine) {
|
|
||||||
int e = output.indexOf('\n', s);
|
|
||||||
return (e < 0 ? output.substring(s) : output.substring(s, e)).trim();
|
|
||||||
}
|
|
||||||
// 取到下一个 === 或末尾
|
|
||||||
int e = output.indexOf("\n===", s);
|
|
||||||
return (e < 0 ? output.substring(s) : output.substring(s, e)).trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析 CPU 段(top -bn1 输出头部)
|
|
||||||
* 格式:Cpu(s): 1.2 us, 0.3 sy, 0.0 ni, 98.3 id, 0.1 wa, 0.1 si
|
|
||||||
*/
|
|
||||||
private static Map<String, String> parseCpu(String block) {
|
|
||||||
Map<String, String> cpu = new LinkedHashMap<>();
|
|
||||||
for (String line : block.split("\n")) {
|
|
||||||
if (line.startsWith("Cpu") || line.startsWith("%Cpu")) {
|
|
||||||
// 统一去掉 %Cpu(s): 前缀
|
|
||||||
String data = line.replaceFirst(".*?:\\s*", "").replaceFirst("^%Cpu\\(s?\\):\\s*", "");
|
|
||||||
for (String part : data.split(",")) {
|
|
||||||
part = part.trim();
|
|
||||||
String[] kv = part.split("\\s+", 2);
|
|
||||||
if (kv.length >= 2) {
|
|
||||||
cpu.put(kv[1].trim(), kv[0].trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析内存段(free -m 输出)
|
|
||||||
* Mem: total used free shared buff/cache available
|
|
||||||
*/
|
|
||||||
private static Map<String, String> parseMemory(String block) {
|
|
||||||
Map<String, String> mem = new LinkedHashMap<>();
|
|
||||||
for (String line : block.split("\n")) {
|
|
||||||
if (line.startsWith("Mem:")) {
|
|
||||||
String[] cols = line.trim().split("\\s+");
|
|
||||||
if (cols.length >= 7) {
|
|
||||||
mem.put("total", cols[1] + " MB");
|
|
||||||
mem.put("used", cols[2] + " MB");
|
|
||||||
mem.put("free", cols[3] + " MB");
|
|
||||||
mem.put("available", cols[6] + " MB");
|
|
||||||
// 使用率
|
|
||||||
try {
|
|
||||||
double total = Double.parseDouble(cols[1]);
|
|
||||||
double used = Double.parseDouble(cols[2]);
|
|
||||||
double pct = total > 0 ? used / total * 100 : 0;
|
|
||||||
mem.put("usagePercent", String.format("%.1f%%", pct));
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析磁盘段(df -h 输出)
|
|
||||||
* Filesystem Size Used Avail Use% Mounted on
|
|
||||||
*/
|
|
||||||
private static List<Map<String, String>> parseDisk(String block) {
|
|
||||||
List<Map<String, String>> disks = new ArrayList<>();
|
|
||||||
String[] lines = block.split("\n");
|
|
||||||
for (int i = 0; i < lines.length; i++) {
|
|
||||||
String line = lines[i].trim();
|
|
||||||
if (i == 0 && (line.startsWith("Filesystem") || line.startsWith("文件系统"))) continue;
|
|
||||||
if (line.isEmpty()) continue;
|
|
||||||
String[] cols = line.split("\\s+");
|
|
||||||
if (cols.length >= 6) {
|
|
||||||
Map<String, String> d = new LinkedHashMap<>();
|
|
||||||
d.put("filesystem", cols[0]);
|
|
||||||
d.put("size", cols[1]);
|
|
||||||
d.put("used", cols[2]);
|
|
||||||
d.put("avail", cols[3]);
|
|
||||||
d.put("usePercent", cols[4]);
|
|
||||||
d.put("mounted", cols[5]);
|
|
||||||
disks.add(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return disks;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------ 重命名/移动
|
// ------------------------------------------------------------------ 重命名/移动
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user