|
@@ -13,26 +13,37 @@ import oshi.software.os.OSFileStore;
|
|
import oshi.software.os.OperatingSystem;
|
|
import oshi.software.os.OperatingSystem;
|
|
import oshi.util.Util;
|
|
import oshi.util.Util;
|
|
|
|
|
|
|
|
+import java.io.BufferedReader;
|
|
|
|
+import java.io.File;
|
|
|
|
+import java.io.FileReader;
|
|
|
|
+import java.io.InputStreamReader;
|
|
import java.net.UnknownHostException;
|
|
import java.net.UnknownHostException;
|
|
-import java.util.LinkedList;
|
|
|
|
-import java.util.List;
|
|
|
|
-import java.util.Properties;
|
|
|
|
-
|
|
|
|
-import static com.ruoyi.framework.web.domain.AdvancedSystemMonitor.advancedSystem;
|
|
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.regex.Matcher;
|
|
|
|
+import java.util.regex.Pattern;
|
|
|
|
|
|
/**
|
|
/**
|
|
* 服务器相关信息
|
|
* 服务器相关信息
|
|
- *
|
|
|
|
|
|
+ *
|
|
* @author ruoyi
|
|
* @author ruoyi
|
|
*/
|
|
*/
|
|
-public class Server
|
|
|
|
-{
|
|
|
|
|
|
+public class Server {
|
|
private static final int OSHI_WAIT_SECOND = 1000;
|
|
private static final int OSHI_WAIT_SECOND = 1000;
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* CPU相关信息
|
|
* CPU相关信息
|
|
*/
|
|
*/
|
|
private Cpu cpu = new Cpu();
|
|
private Cpu cpu = new Cpu();
|
|
|
|
+ private List<Cpu> cpuList = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * GPU
|
|
|
|
+ */
|
|
|
|
+ private List<Gpu> gpuList = new ArrayList<>();
|
|
|
|
+ /**
|
|
|
|
+ * 网络
|
|
|
|
+ */
|
|
|
|
+ private List<Network> netWorkList = new ArrayList<>();
|
|
|
|
|
|
/**
|
|
/**
|
|
* 內存相关信息
|
|
* 內存相关信息
|
|
@@ -54,58 +65,71 @@ public class Server
|
|
*/
|
|
*/
|
|
private List<SysFile> sysFiles = new LinkedList<SysFile>();
|
|
private List<SysFile> sysFiles = new LinkedList<SysFile>();
|
|
|
|
|
|
- public Cpu getCpu()
|
|
|
|
- {
|
|
|
|
|
|
+ public List<Network> getNetWorkList() {
|
|
|
|
+ return netWorkList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void setNetWorkList(List<Network> netWorkList) {
|
|
|
|
+ this.netWorkList = netWorkList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public List<Gpu> getGpuList() {
|
|
|
|
+ return gpuList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void setGpuList(List<Gpu> gpuList) {
|
|
|
|
+ this.gpuList = gpuList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public List<Cpu> getCpuList() {
|
|
|
|
+ return cpuList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void setCpuList(List<Cpu> cpuList) {
|
|
|
|
+ this.cpuList = cpuList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public Cpu getCpu() {
|
|
return cpu;
|
|
return cpu;
|
|
}
|
|
}
|
|
|
|
|
|
- public void setCpu(Cpu cpu)
|
|
|
|
- {
|
|
|
|
|
|
+ public void setCpu(Cpu cpu) {
|
|
this.cpu = cpu;
|
|
this.cpu = cpu;
|
|
}
|
|
}
|
|
|
|
|
|
- public Mem getMem()
|
|
|
|
- {
|
|
|
|
|
|
+ public Mem getMem() {
|
|
return mem;
|
|
return mem;
|
|
}
|
|
}
|
|
|
|
|
|
- public void setMem(Mem mem)
|
|
|
|
- {
|
|
|
|
|
|
+ public void setMem(Mem mem) {
|
|
this.mem = mem;
|
|
this.mem = mem;
|
|
}
|
|
}
|
|
|
|
|
|
- public Jvm getJvm()
|
|
|
|
- {
|
|
|
|
|
|
+ public Jvm getJvm() {
|
|
return jvm;
|
|
return jvm;
|
|
}
|
|
}
|
|
|
|
|
|
- public void setJvm(Jvm jvm)
|
|
|
|
- {
|
|
|
|
|
|
+ public void setJvm(Jvm jvm) {
|
|
this.jvm = jvm;
|
|
this.jvm = jvm;
|
|
}
|
|
}
|
|
|
|
|
|
- public Sys getSys()
|
|
|
|
- {
|
|
|
|
|
|
+ public Sys getSys() {
|
|
return sys;
|
|
return sys;
|
|
}
|
|
}
|
|
|
|
|
|
- public void setSys(Sys sys)
|
|
|
|
- {
|
|
|
|
|
|
+ public void setSys(Sys sys) {
|
|
this.sys = sys;
|
|
this.sys = sys;
|
|
}
|
|
}
|
|
|
|
|
|
- public List<SysFile> getSysFiles()
|
|
|
|
- {
|
|
|
|
|
|
+ public List<SysFile> getSysFiles() {
|
|
return sysFiles;
|
|
return sysFiles;
|
|
}
|
|
}
|
|
|
|
|
|
- public void setSysFiles(List<SysFile> sysFiles)
|
|
|
|
- {
|
|
|
|
|
|
+ public void setSysFiles(List<SysFile> sysFiles) {
|
|
this.sysFiles = sysFiles;
|
|
this.sysFiles = sysFiles;
|
|
}
|
|
}
|
|
|
|
|
|
- public void copyTo() throws Exception
|
|
|
|
- {
|
|
|
|
|
|
+ public void copyTo() throws Exception {
|
|
SystemInfo si = new SystemInfo();
|
|
SystemInfo si = new SystemInfo();
|
|
HardwareAbstractionLayer hal = si.getHardware();
|
|
HardwareAbstractionLayer hal = si.getHardware();
|
|
|
|
|
|
@@ -119,40 +143,417 @@ public class Server
|
|
|
|
|
|
setSysFiles(si.getOperatingSystem());
|
|
setSysFiles(si.getOperatingSystem());
|
|
|
|
|
|
- advancedSystem();
|
|
|
|
|
|
+ setGpuInfo();
|
|
|
|
+
|
|
|
|
+ List<String> interfaceNameList = new ArrayList<>();
|
|
|
|
+ interfaceNameList.add("eno1np0");// 替换为你的网卡名称
|
|
|
|
+ interfaceNameList.add("eno2np1");// 替换为你的网卡名称
|
|
|
|
+ for (String interfaceName : interfaceNameList) {
|
|
|
|
+ Network netWork = new Network();
|
|
|
|
+ NetworkStats stats1 = getNetworkStats(interfaceName);
|
|
|
|
+ if (stats1 != null) {
|
|
|
|
+ Util.sleep(OSHI_WAIT_SECOND);
|
|
|
|
+ NetworkStats stats2 = getNetworkStats(interfaceName);
|
|
|
|
+ long rxRate = (stats2.rxBytes - stats1.rxBytes) * 8; // 比特/秒
|
|
|
|
+ long txRate = (stats2.txBytes - stats1.txBytes) * 8; // 比特/秒
|
|
|
|
+ netWork.setNetworkName(interfaceName);
|
|
|
|
+ netWork.setNetworkUp(txRate);
|
|
|
|
+ netWork.setNetworkDown(rxRate);
|
|
|
|
+ netWorkList.add(netWork);
|
|
|
|
+ System.out.printf("\n网络速率 (%s):\n 下行: %s\n 上行: %s\n",
|
|
|
|
+ interfaceName,
|
|
|
|
+ formatRate(rxRate),
|
|
|
|
+ formatRate(txRate)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 网络统计数据结构
|
|
|
|
+ private static class NetworkStats {
|
|
|
|
+ long rxBytes;
|
|
|
|
+ long txBytes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取网络统计信息
|
|
|
|
+ private static NetworkStats getNetworkStats(String interfaceName) throws Exception {
|
|
|
|
+ File file = new File("/proc/net/dev");
|
|
|
|
+ if (file == null || !file.exists()) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ NetworkStats stats = new NetworkStats();
|
|
|
|
+ try (BufferedReader br = new BufferedReader(new FileReader(file))) {
|
|
|
|
+ String line;
|
|
|
|
+ while ((line = br.readLine()) != null) {
|
|
|
|
+ line = line.trim();
|
|
|
|
+ if (line.startsWith(interfaceName + ":")) {
|
|
|
|
+ String[] parts = line.split("\\s+");
|
|
|
|
+ stats.rxBytes = Long.parseLong(parts[1]);
|
|
|
|
+ stats.txBytes = Long.parseLong(parts[9]);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return stats;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 格式化网络速率
|
|
|
|
+ private static String formatRate(long rateBitsPerSec) {
|
|
|
|
+ if (rateBitsPerSec < 1000) {
|
|
|
|
+ return rateBitsPerSec + " bps";
|
|
|
|
+ } else if (rateBitsPerSec < 1_000_000) {
|
|
|
|
+ return String.format("%.2f Kbps", rateBitsPerSec / 1000.0);
|
|
|
|
+ } else if (rateBitsPerSec < 1_000_000_000) {
|
|
|
|
+ return String.format("%.2f Mbps", rateBitsPerSec / 1_000_000.0);
|
|
|
|
+ } else {
|
|
|
|
+ return String.format("%.2f Gbps", rateBitsPerSec / 1_000_000_000.0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void setGpuInfo() {
|
|
|
|
+ // 3. 获取所有GPU信息
|
|
|
|
+ List<Map<String, String>> gpuInfoList = getMultiGpuInfo();
|
|
|
|
+ for (int i = 0; i < gpuInfoList.size(); i++) {
|
|
|
|
+ Gpu gpu = new Gpu();
|
|
|
|
+ System.out.println("\nGPU #" + i + " 信息:");
|
|
|
|
+ for (Map<String, String> stringStringMap : gpuInfoList) {
|
|
|
|
+ gpu.setName(stringStringMap.get("名称"));
|
|
|
|
+ gpu.setGpuMemory(stringStringMap.get("总显存"));
|
|
|
|
+ gpu.setUseMemory(stringStringMap.get("显存使用"));
|
|
|
|
+ gpu.setUsed(stringStringMap.get("使用率"));
|
|
|
|
+ gpu.setTemperature(stringStringMap.get("温度"));
|
|
|
|
+ gpu.setPower(stringStringMap.get("功耗"));
|
|
|
|
+ gpuList.add(gpu);
|
|
|
|
+ }
|
|
|
|
+ gpuInfoList.get(i).forEach((key, value) ->
|
|
|
|
+ System.out.println(" " + key + ": " + value)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取多GPU信息
|
|
|
|
+ private static List<Map<String, String>> getMultiGpuInfo() {
|
|
|
|
+ List<Map<String, String>> gpuList = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+ // 使用nvidia-smi获取多GPU信息
|
|
|
|
+ try {
|
|
|
|
+ Process process = Runtime.getRuntime().exec(
|
|
|
|
+ "nvidia-smi --query-gpu=index,name,temperature.gpu,utilization.gpu,memory.used,memory.total,power.draw,power.limit,clocks.current.graphics,clocks.current.memory --format=csv,noheader,nounits"
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
|
|
+ String line;
|
|
|
|
+ int gpuIndex = 0;
|
|
|
|
+
|
|
|
|
+ while ((line = reader.readLine()) != null) {
|
|
|
|
+ String[] parts = line.split(", ");
|
|
|
|
+ if (parts.length >= 10) {
|
|
|
|
+ Map<String, String> gpuInfo = new HashMap<>();
|
|
|
|
+ gpuInfo.put("索引", parts[0].trim());
|
|
|
|
+ gpuInfo.put("名称", parts[1].trim());
|
|
|
|
+ gpuInfo.put("温度", parts[2].trim() + "°C");
|
|
|
|
+ gpuInfo.put("使用率", parts[3].trim() + "%");
|
|
|
|
+ gpuInfo.put("显存使用", parts[4].trim() + " MB");
|
|
|
|
+ gpuInfo.put("总显存", parts[5].trim() + " MB");
|
|
|
|
+ gpuInfo.put("功耗", parts[6].trim() + " W");
|
|
|
|
+ gpuInfo.put("功耗限制", parts[7].trim() + " W");
|
|
|
|
+ gpuInfo.put("图形时钟", parts[8].trim() + " MHz");
|
|
|
|
+ gpuInfo.put("显存时钟", parts[9].trim() + " MHz");
|
|
|
|
+ gpuList.add(gpuInfo);
|
|
|
|
+ gpuIndex++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 检查是否有GPU被检测到
|
|
|
|
+ if (gpuIndex > 0) return gpuList;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.err.println("nvidia-smi执行错误: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 备用方法:尝试从sysfs读取AMD/集成GPU信息
|
|
|
|
+ try {
|
|
|
|
+ File hwmonDir = new File("/sys/class/hwmon/");
|
|
|
|
+ for (File hwmon : hwmonDir.listFiles()) {
|
|
|
|
+ try {
|
|
|
|
+ // 检测是否为GPU
|
|
|
|
+ File nameFile = new File(hwmon, "name");
|
|
|
|
+ if (!nameFile.exists()) continue;
|
|
|
|
+
|
|
|
|
+ try (BufferedReader nameReader = new BufferedReader(new FileReader(nameFile))) {
|
|
|
|
+ String name = nameReader.readLine();
|
|
|
|
+ if (name == null || !(name.contains("amdgpu") || name.contains("radeon"))) continue;
|
|
|
|
+
|
|
|
|
+ Map<String, String> gpuInfo = new HashMap<>();
|
|
|
|
+ gpuInfo.put("类型", name);
|
|
|
|
+
|
|
|
|
+ // 读取温度
|
|
|
|
+ for (int i = 1; i <= 5; i++) {
|
|
|
|
+ File tempFile = new File(hwmon, "temp" + i + "_input");
|
|
|
|
+ if (tempFile.exists()) {
|
|
|
|
+ try (BufferedReader tempReader = new BufferedReader(new FileReader(tempFile))) {
|
|
|
|
+ double temp = Double.parseDouble(tempReader.readLine().trim()) / 1000.0;
|
|
|
|
+ gpuInfo.put("温度", String.format("%.1f°C", temp));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 读取功耗(如果可用)
|
|
|
|
+ File powerFile = new File(hwmon, "power1_average");
|
|
|
|
+ if (powerFile.exists()) {
|
|
|
|
+ try (BufferedReader powerReader = new BufferedReader(new FileReader(powerFile))) {
|
|
|
|
+ double power = Double.parseDouble(powerReader.readLine().trim()) / 1_000_000.0;
|
|
|
|
+ gpuInfo.put("功耗", String.format("%.1f W", power));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ gpuList.add(gpuInfo);
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // 继续下一个hwmon
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.err.println("sysfs读取错误: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 如果没有检测到GPU,添加一个错误信息
|
|
|
|
+ if (gpuList.isEmpty()) {
|
|
|
|
+ Map<String, String> errorInfo = new HashMap<>();
|
|
|
|
+ errorInfo.put("错误", "未检测到GPU或需要安装驱动");
|
|
|
|
+ gpuList.add(errorInfo);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return gpuList;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* 设置CPU信息
|
|
* 设置CPU信息
|
|
*/
|
|
*/
|
|
- private void setCpuInfo(CentralProcessor processor)
|
|
|
|
- {
|
|
|
|
- // CPU信息
|
|
|
|
- long[] prevTicks = processor.getSystemCpuLoadTicks();
|
|
|
|
- Util.sleep(OSHI_WAIT_SECOND);
|
|
|
|
- long[] ticks = processor.getSystemCpuLoadTicks();
|
|
|
|
- long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
|
|
|
|
- long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
|
|
|
|
- long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
|
|
|
|
- long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
|
|
|
|
- long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
|
|
|
|
- long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
|
|
|
|
- long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
|
|
|
|
- long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
|
|
|
|
- long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
|
|
|
|
- cpu.setCpuNum(processor.getLogicalProcessorCount());
|
|
|
|
- cpu.setTotal(totalCpu);
|
|
|
|
- cpu.setSys(cSys);
|
|
|
|
- cpu.setUsed(user);
|
|
|
|
- cpu.setWait(iowait);
|
|
|
|
- cpu.setFree(idle);
|
|
|
|
|
|
+ private void setCpuInfo(CentralProcessor processor) {
|
|
|
|
+ // 1. 获取物理CPU数量
|
|
|
|
+ int physicalPackageCount = processor.getPhysicalPackageCount();
|
|
|
|
+ System.out.println("物理CPU数量: " + physicalPackageCount);
|
|
|
|
+ if (physicalPackageCount < 2) {
|
|
|
|
+ // CPU信息
|
|
|
|
+ long[] prevTicks = processor.getSystemCpuLoadTicks();
|
|
|
|
+ Util.sleep(OSHI_WAIT_SECOND);
|
|
|
|
+ long[] ticks = processor.getSystemCpuLoadTicks();
|
|
|
|
+ long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
|
|
|
|
+ long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
|
|
|
|
+ long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
|
|
|
|
+ long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
|
|
|
|
+ long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
|
|
|
|
+ long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
|
|
|
|
+ long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
|
|
|
|
+ long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
|
|
|
|
+ long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
|
|
|
|
+ cpu.setCpuNum(processor.getLogicalProcessorCount());
|
|
|
|
+ cpu.setTotal(totalCpu);
|
|
|
|
+ cpu.setSys(cSys);
|
|
|
|
+ cpu.setUsed(user);
|
|
|
|
+ cpu.setWait(iowait);
|
|
|
|
+ cpu.setFree(idle);
|
|
|
|
+ cpuList.add(cpu);
|
|
|
|
+ } else {
|
|
|
|
+ // 2分组方法:使用物理处理器编号分组
|
|
|
|
+ Map<Integer, List<CentralProcessor.LogicalProcessor>> cpuGroups = new HashMap<>();
|
|
|
|
+ for (CentralProcessor.LogicalProcessor lp : processor.getLogicalProcessors()) {
|
|
|
|
+ int packageId = lp.getPhysicalProcessorNumber() % physicalPackageCount;
|
|
|
|
+ cpuGroups.computeIfAbsent(packageId, k -> new ArrayList<>()).add(lp);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 3. 获取初始CPU滴答计数
|
|
|
|
+ long[] initialSystemTicks = processor.getSystemCpuLoadTicks();
|
|
|
|
+
|
|
|
|
+ // 4. 等待1秒获取新数据
|
|
|
|
+ Util.sleep(OSHI_WAIT_SECOND);
|
|
|
|
+
|
|
|
|
+ // 5. 获取新的CPU滴答计数
|
|
|
|
+ long[] newSystemTicks = processor.getSystemCpuLoadTicks();
|
|
|
|
+
|
|
|
|
+ // 6. 计算并显示每个物理CPU的数据
|
|
|
|
+ for (int pkgId = 0; pkgId < physicalPackageCount; pkgId++) {
|
|
|
|
+ Cpu cpuOne = new Cpu();
|
|
|
|
+ if (!cpuGroups.containsKey(pkgId)) continue;
|
|
|
|
+ System.out.println("\n===== 物理CPU " + (pkgId + 1) + " 数据 =====");
|
|
|
|
+ System.out.println("包含的逻辑处理器数量: " + cpuGroups.get(pkgId).size());
|
|
|
|
+ cpuOne.setCpuNum(cpuGroups.get(pkgId).size());
|
|
|
|
+ // 计算该物理CPU的负载
|
|
|
|
+ double load = calculateCpuLoad(initialSystemTicks, newSystemTicks);
|
|
|
|
+ System.out.printf("总负载: %.1f%%\n", load * 100);
|
|
|
|
+ cpuOne.setTotal(load * 100);
|
|
|
|
+ cpuOne.setSys(newSystemTicks[CentralProcessor.TickType.SYSTEM.getIndex()]);
|
|
|
|
+ cpuOne.setUsed(newSystemTicks[CentralProcessor.TickType.USER.getIndex()]);
|
|
|
|
+ cpuOne.setWait(newSystemTicks[CentralProcessor.TickType.IOWAIT.getIndex()]);
|
|
|
|
+ cpuOne.setFree(newSystemTicks[CentralProcessor.TickType.IDLE.getIndex()]);
|
|
|
|
+ // 显示详细负载数据
|
|
|
|
+ printCpuLoadDetails(newSystemTicks);
|
|
|
|
+ cpuList.add(cpuOne);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 1. 获取所有CPU插槽的温度
|
|
|
|
+ Map<Integer, Double> cpuTemps = getCpuTemperatures();
|
|
|
|
+ if (cpuTemps != null) {
|
|
|
|
+ for (Integer socket : cpuTemps.keySet()) {
|
|
|
|
+ Double temp = cpuTemps.get(socket);
|
|
|
|
+ cpuList.get(socket).setTemperature(temp);
|
|
|
|
+ System.out.printf("CPU插槽 %d 温度: %.1f°C\n", socket, temp);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取双CPU温度
|
|
|
|
+ private static Map<Integer, Double> getCpuTemperatures() {
|
|
|
|
+ Map<Integer, Double> temps = new HashMap<>();
|
|
|
|
+
|
|
|
|
+ // 方法1: 使用sensors命令(最可靠)
|
|
|
|
+ try {
|
|
|
|
+ Process process = Runtime.getRuntime().exec("sensors");
|
|
|
|
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
|
|
+ String line;
|
|
|
|
+
|
|
|
|
+ while ((line = reader.readLine()) != null) {
|
|
|
|
+ // 匹配物理CPU的温度(Package或Tdie)
|
|
|
|
+ if (line.contains("Package id") || line.contains("Tdie") || line.contains("Tccd1")) {
|
|
|
|
+ // 提取温度值
|
|
|
|
+ Pattern tempPattern = Pattern.compile("\\+([\\d\\.]+)°C");
|
|
|
|
+ Matcher matcher = tempPattern.matcher(line);
|
|
|
|
+ if (matcher.find()) {
|
|
|
|
+ double temp = Double.parseDouble(matcher.group(1));
|
|
|
|
+
|
|
|
|
+ // 提取CPU插槽ID
|
|
|
|
+ Pattern socketPattern = Pattern.compile("id\\s*(\\d+)");
|
|
|
|
+ Matcher socketMatcher = socketPattern.matcher(line);
|
|
|
|
+ int socketId = socketMatcher.find() ? Integer.parseInt(socketMatcher.group(1)) : 0;
|
|
|
|
+
|
|
|
|
+ temps.put(socketId, temp);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!temps.isEmpty()) return temps;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.err.println("sensors命令执行错误: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 方法2: 通过hwmon接口获取
|
|
|
|
+ try {
|
|
|
|
+ File hwmonDir = new File("/sys/class/hwmon/");
|
|
|
|
+ for (File hwmon : hwmonDir.listFiles()) {
|
|
|
|
+ try {
|
|
|
|
+ // 检测是否为CPU温度传感器
|
|
|
|
+ File nameFile = new File(hwmon, "name");
|
|
|
|
+ if (!nameFile.exists()) continue;
|
|
|
|
+
|
|
|
|
+ try (BufferedReader nameReader = new BufferedReader(new FileReader(nameFile))) {
|
|
|
|
+ String name = nameReader.readLine();
|
|
|
|
+ if (name == null || !(name.contains("coretemp") || name.contains("k10temp"))) continue;
|
|
|
|
+
|
|
|
|
+ // 查找所有物理CPU的温度
|
|
|
|
+ for (int i = 1; i <= 16; i++) {
|
|
|
|
+ File tempFile = new File(hwmon, "temp" + i + "_input");
|
|
|
|
+ File labelFile = new File(hwmon, "temp" + i + "_label");
|
|
|
|
+
|
|
|
|
+ if (tempFile.exists() && labelFile.exists()) {
|
|
|
|
+ // 读取温度标签确定是物理CPU
|
|
|
|
+ String label;
|
|
|
|
+ try (BufferedReader labelReader = new BufferedReader(new FileReader(labelFile))) {
|
|
|
|
+ label = labelReader.readLine();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 只获取物理CPU温度(Package或Tdie)
|
|
|
|
+ if (label != null && (label.contains("Package") || label.contains("Tdie"))) {
|
|
|
|
+ try (BufferedReader tempReader = new BufferedReader(new FileReader(tempFile))) {
|
|
|
|
+ double temp = Double.parseDouble(tempReader.readLine().trim()) / 1000.0;
|
|
|
|
+ // 提取CPU插槽ID
|
|
|
|
+ int socketId = 0;
|
|
|
|
+ Pattern p = Pattern.compile("(\\d+)");
|
|
|
|
+ Matcher m = p.matcher(label);
|
|
|
|
+ if (m.find()) socketId = Integer.parseInt(m.group());
|
|
|
|
+
|
|
|
|
+ temps.put(socketId, temp);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // 继续下一个hwmon
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!temps.isEmpty()) return temps;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.err.println("hwmon接口访问错误: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 方法3: 通过thermal_zone获取
|
|
|
|
+ try {
|
|
|
|
+ File thermalDir = new File("/sys/class/thermal/");
|
|
|
|
+ int socketCount = 0;
|
|
|
|
+
|
|
|
|
+ for (File zone : thermalDir.listFiles()) {
|
|
|
|
+ if (zone.getName().startsWith("thermal_zone")) {
|
|
|
|
+ // 检查类型
|
|
|
|
+ File typeFile = new File(zone, "type");
|
|
|
|
+ if (!typeFile.exists()) continue;
|
|
|
|
+
|
|
|
|
+ try (BufferedReader typeReader = new BufferedReader(new FileReader(typeFile))) {
|
|
|
|
+ String type = typeReader.readLine();
|
|
|
|
+ if (type == null || !(type.contains("x86_pkg_temp") || type.contains("acpitz"))) continue;
|
|
|
|
+
|
|
|
|
+ // 读取温度
|
|
|
|
+ File tempFile = new File(zone, "temp");
|
|
|
|
+ if (tempFile.exists()) {
|
|
|
|
+ try (BufferedReader tempReader = new BufferedReader(new FileReader(tempFile))) {
|
|
|
|
+ double temp = Double.parseDouble(tempReader.readLine().trim()) / 1000.0;
|
|
|
|
+ temps.put(socketCount++, temp);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!temps.isEmpty()) return temps;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.err.println("thermal_zone访问错误: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ System.out.println("无法检测到CPU温度传感器");
|
|
|
|
+ return temps;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static void printCpuLoadDetails(long[] ticks) {
|
|
|
|
+ System.out.println("详细负载数据:");
|
|
|
|
+ System.out.printf(" User: %d\n", ticks[CentralProcessor.TickType.USER.getIndex()]);
|
|
|
|
+ System.out.printf(" Nice: %d\n", ticks[CentralProcessor.TickType.NICE.getIndex()]);
|
|
|
|
+ System.out.printf(" System: %d\n", ticks[CentralProcessor.TickType.SYSTEM.getIndex()]);
|
|
|
|
+ System.out.printf(" Idle: %d\n", ticks[CentralProcessor.TickType.IDLE.getIndex()]);
|
|
|
|
+ System.out.printf(" IOWait: %d\n", ticks[CentralProcessor.TickType.IOWAIT.getIndex()]);
|
|
|
|
+ System.out.printf(" IRQ: %d\n", ticks[CentralProcessor.TickType.IRQ.getIndex()]);
|
|
|
|
+ System.out.printf(" SoftIRQ:%d\n", ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()]);
|
|
|
|
+ System.out.printf(" Steal: %d\n", ticks[CentralProcessor.TickType.STEAL.getIndex()]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static double calculateCpuLoad(long[] initialTicks, long[] newTicks) {
|
|
|
|
+ long user = newTicks[CentralProcessor.TickType.USER.getIndex()] - initialTicks[CentralProcessor.TickType.USER.getIndex()];
|
|
|
|
+ long nice = newTicks[CentralProcessor.TickType.NICE.getIndex()] - initialTicks[CentralProcessor.TickType.NICE.getIndex()];
|
|
|
|
+ long system = newTicks[CentralProcessor.TickType.SYSTEM.getIndex()] - initialTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
|
|
|
|
+ long idle = newTicks[CentralProcessor.TickType.IDLE.getIndex()] - initialTicks[CentralProcessor.TickType.IDLE.getIndex()];
|
|
|
|
+ long iowait = newTicks[CentralProcessor.TickType.IOWAIT.getIndex()] - initialTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
|
|
|
|
+ long irq = newTicks[CentralProcessor.TickType.IRQ.getIndex()] - initialTicks[CentralProcessor.TickType.IRQ.getIndex()];
|
|
|
|
+ long softirq = newTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - initialTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
|
|
|
|
+ long steal = newTicks[CentralProcessor.TickType.STEAL.getIndex()] - initialTicks[CentralProcessor.TickType.STEAL.getIndex()];
|
|
|
|
+ long totalUsed = user + nice + system + irq + softirq + steal;
|
|
|
|
+ long total = totalUsed + idle + iowait;
|
|
|
|
+
|
|
|
|
+ return total > 0 ? (double) totalUsed / total : 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* 设置内存信息
|
|
* 设置内存信息
|
|
*/
|
|
*/
|
|
- private void setMemInfo(GlobalMemory memory)
|
|
|
|
- {
|
|
|
|
|
|
+ private void setMemInfo(GlobalMemory memory) {
|
|
mem.setTotal(memory.getTotal());
|
|
mem.setTotal(memory.getTotal());
|
|
mem.setUsed(memory.getTotal() - memory.getAvailable());
|
|
mem.setUsed(memory.getTotal() - memory.getAvailable());
|
|
mem.setFree(memory.getAvailable());
|
|
mem.setFree(memory.getAvailable());
|
|
@@ -161,8 +562,7 @@ public class Server
|
|
/**
|
|
/**
|
|
* 设置服务器信息
|
|
* 设置服务器信息
|
|
*/
|
|
*/
|
|
- private void setSysInfo()
|
|
|
|
- {
|
|
|
|
|
|
+ private void setSysInfo() {
|
|
Properties props = System.getProperties();
|
|
Properties props = System.getProperties();
|
|
sys.setComputerName(IpUtils.getHostName());
|
|
sys.setComputerName(IpUtils.getHostName());
|
|
sys.setComputerIp(IpUtils.getHostIp());
|
|
sys.setComputerIp(IpUtils.getHostIp());
|
|
@@ -174,8 +574,7 @@ public class Server
|
|
/**
|
|
/**
|
|
* 设置Java虚拟机
|
|
* 设置Java虚拟机
|
|
*/
|
|
*/
|
|
- private void setJvmInfo() throws UnknownHostException
|
|
|
|
- {
|
|
|
|
|
|
+ private void setJvmInfo() throws UnknownHostException {
|
|
Properties props = System.getProperties();
|
|
Properties props = System.getProperties();
|
|
jvm.setTotal(Runtime.getRuntime().totalMemory());
|
|
jvm.setTotal(Runtime.getRuntime().totalMemory());
|
|
jvm.setMax(Runtime.getRuntime().maxMemory());
|
|
jvm.setMax(Runtime.getRuntime().maxMemory());
|
|
@@ -187,12 +586,10 @@ public class Server
|
|
/**
|
|
/**
|
|
* 设置磁盘信息
|
|
* 设置磁盘信息
|
|
*/
|
|
*/
|
|
- private void setSysFiles(OperatingSystem os)
|
|
|
|
- {
|
|
|
|
|
|
+ private void setSysFiles(OperatingSystem os) {
|
|
FileSystem fileSystem = os.getFileSystem();
|
|
FileSystem fileSystem = os.getFileSystem();
|
|
List<OSFileStore> fsArray = fileSystem.getFileStores();
|
|
List<OSFileStore> fsArray = fileSystem.getFileStores();
|
|
- for (OSFileStore fs : fsArray)
|
|
|
|
- {
|
|
|
|
|
|
+ for (OSFileStore fs : fsArray) {
|
|
long free = fs.getUsableSpace();
|
|
long free = fs.getUsableSpace();
|
|
long total = fs.getTotalSpace();
|
|
long total = fs.getTotalSpace();
|
|
long used = total - free;
|
|
long used = total - free;
|
|
@@ -210,31 +607,23 @@ public class Server
|
|
|
|
|
|
/**
|
|
/**
|
|
* 字节转换
|
|
* 字节转换
|
|
- *
|
|
|
|
|
|
+ *
|
|
* @param size 字节大小
|
|
* @param size 字节大小
|
|
* @return 转换后值
|
|
* @return 转换后值
|
|
*/
|
|
*/
|
|
- public String convertFileSize(long size)
|
|
|
|
- {
|
|
|
|
|
|
+ public String convertFileSize(long size) {
|
|
long kb = 1024;
|
|
long kb = 1024;
|
|
long mb = kb * 1024;
|
|
long mb = kb * 1024;
|
|
long gb = mb * 1024;
|
|
long gb = mb * 1024;
|
|
- if (size >= gb)
|
|
|
|
- {
|
|
|
|
|
|
+ if (size >= gb) {
|
|
return String.format("%.1f GB", (float) size / gb);
|
|
return String.format("%.1f GB", (float) size / gb);
|
|
- }
|
|
|
|
- else if (size >= mb)
|
|
|
|
- {
|
|
|
|
|
|
+ } else if (size >= mb) {
|
|
float f = (float) size / mb;
|
|
float f = (float) size / mb;
|
|
return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
|
|
return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
|
|
- }
|
|
|
|
- else if (size >= kb)
|
|
|
|
- {
|
|
|
|
|
|
+ } else if (size >= kb) {
|
|
float f = (float) size / kb;
|
|
float f = (float) size / kb;
|
|
return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
|
|
return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
|
|
+ } else {
|
|
return String.format("%d B", size);
|
|
return String.format("%d B", size);
|
|
}
|
|
}
|
|
}
|
|
}
|