Przeglądaj źródła

FIX 任务,算法,温度 完成

tjf 1 dzień temu
rodzic
commit
b1601f129b

+ 2 - 2
ruoyi-admin/src/main/resources/application.yml

@@ -19,8 +19,8 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-          active: druid
-#          active: prod
+#          active: druid
+          active: prod
   # 文件上传
   servlet:
     multipart:

+ 213 - 123
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java

@@ -339,28 +339,29 @@ public class Server {
             cpuGroups.computeIfAbsent(packageId, k -> new ArrayList<>()).add(lp);
         }
 
-        // 3. 获取初始CPU滴答计数
-        long[] initialSystemTicks = processor.getSystemCpuLoadTicks();
+        // 3. 获取初始CPU滴答计数(按逻辑处理器)
+        long[][] initialTicks = processor.getProcessorCpuLoadTicks();
 
         // 4. 等待1秒获取新数据
         Util.sleep(OSHI_WAIT_SECOND);
 
         // 5. 获取新的CPU滴答计数
-        long[] newSystemTicks = processor.getSystemCpuLoadTicks();
+        long[][] newTicks = processor.getProcessorCpuLoadTicks();
 
         // 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) + " 数据 =====");
+            List<CentralProcessor.LogicalProcessor> group = cpuGroups.get(pkgId);
             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(Arith.round(load * 100, 2));
-            // 显示详细负载数据
-            calculateDetailedCpuLoad(initialSystemTicks, newSystemTicks, cpuOne);
+            // 计算该物理CPU的负载百分比
+            double totalLoad = calculatePackageLoad(initialTicks, newTicks, group);
+            System.out.printf("总负载: %.2f%%\n", totalLoad * 100);
+            cpuOne.setTotal(Arith.round(totalLoad * 100, 2));
+            // 计算并显示各个详细负载的百分比
+            printPackageLoadDetails(initialTicks, newTicks, group, cpuOne);
             cpuList.add(cpuOne);
         }
 
@@ -525,173 +526,262 @@ public class Server {
         System.out.println("无法检测到CPU速度");
         return speeds;
     }
-
     // 获取双CPU温度
+
     private static Map<Integer, Double> getCpuTemperatures() {
         Map<Integer, Double> temps = new HashMap<>();
+        int cpuCount = 0;
 
-        // 方法1: 使用sensors命令(最可靠)
+        // 方法1: 使用sensors命令并解析文本输出
         try {
             Process process = Runtime.getRuntime().exec("sensors");
             BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
             String line;
+            boolean inCpuSection = false;
+            boolean foundTctl = false;
 
             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);
+                line = line.trim();
+
+                // 1. 检测适配器部分开始
+                if (line.endsWith(":") || (line.contains("Adapter:") && !line.contains(":"))) {
+                    // 检查是否是CPU适配器
+                    inCpuSection = isCpuAdapterSection(line);
+                    foundTctl = false;
+                    continue;
+                }
+
+                // 2. 在CPU部分处理温度行
+                if (inCpuSection) {
+                    // 3. 检测CPU温度行 (Tctl, Tdie, Package)
+                    if (isCpuTemperatureLine(line)) {
+                        // 提取温度值
+                        Double temp = extractTemperatureValue(line);
+                        if (temp != null) {
+                            temps.put(cpuCount, temp);
+                            System.out.println("检测到CPU " + cpuCount + " 温度: " + temp + "°C");
+                            foundTctl = true;
+                        }
+                    }
+                    // 4. 当检测到非温度行且已有温度值时,结束当前CPU部分
+                    else if (foundTctl && !line.isEmpty()) {
+                        inCpuSection = false;
+                        cpuCount++;
                     }
                 }
             }
 
+            // 处理最后一个CPU部分
+            if (foundTctl) {
+                cpuCount++;
+            }
+
             if (!temps.isEmpty()) return temps;
         } catch (Exception e) {
             System.err.println("sensors命令执行错误: " + e.getMessage());
         }
 
-        // 方法2: 通过hwmon接口获取
+        // 方法2: 备用方案 - 直接搜索所有温度行
+        if (temps.isEmpty()) {
+            try {
+                Process process = Runtime.getRuntime().exec("sensors");
+                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+                String line;
+                int cpuIndex = 0;
+
+                while ((line = reader.readLine()) != null) {
+                    if (isCpuTemperatureLine(line)) {
+                        Double temp = extractTemperatureValue(line);
+                        if (temp != null) {
+                            temps.put(cpuIndex++, temp);
+                            System.out.println("通过备用方法检测到CPU " + (cpuIndex-1) + " 温度: " + temp + "°C");
+                        }
+                    }
+                }
+
+                if (!temps.isEmpty()) return temps;
+            } catch (Exception e) {
+                System.err.println("备用sensors解析错误: " + e.getMessage());
+            }
+        }
+
+        // 方法3: 使用hwmon接口(不依赖固定名称)
         try {
             File hwmonDir = new File("/sys/class/hwmon/");
-            for (File hwmon : hwmonDir.listFiles()) {
+            File[] hwmonDirs = hwmonDir.listFiles();
+            if (hwmonDirs == null) return temps;
+
+            for (File hwmon : hwmonDirs) {
                 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特征的文件
+                    File[] labelFiles = hwmon.listFiles((dir, filename) ->
+                            filename.startsWith("temp") && filename.endsWith("_label"));
 
-                        // 查找所有物理CPU的温度
-                        for (int i = 1; i <= 16; i++) {
-                            File tempFile = new File(hwmon, "temp" + i + "_input");
-                            File labelFile = new File(hwmon, "temp" + i + "_label");
+                    for (File labelFile : labelFiles) {
+                        String baseName = labelFile.getName().replace("_label", "");
+                        File tempFile = new File(hwmon, baseName + "_input");
 
-                            if (tempFile.exists() && labelFile.exists()) {
-                                // 读取温度标签确定是物理CPU
-                                String label;
-                                try (BufferedReader labelReader = new BufferedReader(new FileReader(labelFile))) {
-                                    label = labelReader.readLine();
-                                }
+                        if (!tempFile.exists()) continue;
 
-                                // 只获取物理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);
-                                    }
-                                }
+                        // 读取温度标签
+                        String label;
+                        try (BufferedReader labelReader = new BufferedReader(new FileReader(labelFile))) {
+                            label = labelReader.readLine();
+                        }
+
+                        // 检测物理CPU温度特征
+                        if (isCpuTemperatureLabel(label)) {
+                            // 读取温度值
+                            double temp;
+                            try (BufferedReader tempReader = new BufferedReader(new FileReader(tempFile))) {
+                                temp = Double.parseDouble(tempReader.readLine().trim()) / 1000.0;
                             }
+
+                            // 添加到结果
+                            temps.put(cpuCount, temp);
+                            System.out.println("通过hwmon检测到CPU " + cpuCount + " 温度: " + temp + "°C");
+                            cpuCount++;
                         }
                     }
                 } catch (Exception e) {
-                    // 继续下一个hwmon
+                    System.err.println("hwmon处理错误: " + hwmon.getName() + " - " + e.getMessage());
                 }
             }
-
-            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());
+        if (temps.isEmpty()) {
+            System.out.println("无法检测到CPU温度传感器");
         }
-        System.out.println("无法检测到CPU温度传感器");
         return temps;
     }
 
-    private static void calculateDetailedCpuLoad(long[] initialTicks, long[] newTicks, Cpu cpuOne) {
-        // 计算各类型时间增量
-        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()];
+    // 判断是否CPU适配器部分
+    private static boolean isCpuAdapterSection(String line) {
+        // 空行或包含非CPU设备特征
+        if (line.isEmpty() || line.contains("nvme") || line.contains("bnxt") ||
+                line.contains("Composite") || line.contains("Sensor")) {
+            return false;
+        }
 
-        // 计算总时间(所有类型增量之和)
-        long total = user + nice + system + idle + iowait + irq + softirq + steal;
+        // 包含CPU特征
+        return line.contains("temp") || line.contains("Adapter") ||
+                line.contains("k10") || line.contains("core");
+    }
+
+    // 判断是否CPU温度行
+    private static boolean isCpuTemperatureLine(String line) {
+        if (line.isEmpty()) return false;
+
+        // 匹配CPU温度特征
+        return line.startsWith("Tctl:") ||
+                line.startsWith("Tdie:") ||
+                line.startsWith("Package id") ||
+                line.startsWith("CPU Package") ||
+                line.contains("Core") ||
+                (line.contains("°C") && (line.contains("Package") || line.contains("Core")));
+    }
+
+    // 提取温度值
+    private static Double extractTemperatureValue(String line) {
+        // 匹配温度模式:+34.6°C 或 34.6
+        Pattern pattern = Pattern.compile("([+-]?[\\d\\.]+)\\s*°?C");
+        Matcher matcher = pattern.matcher(line);
+        if (matcher.find()) {
+            try {
+                return Double.parseDouble(matcher.group(1));
+            } catch (NumberFormatException e) {
+                return null;
+            }
+        }
+        return null;
+    }
+
+    // 判断是否CPU温度标签
+    private static boolean isCpuTemperatureLabel(String label) {
+        if (label == null) return false;
+
+        // 匹配CPU温度特征
+        return label.contains("Tctl") ||
+                label.contains("Tdie") ||
+                label.contains("Package") ||
+                label.contains("Core") ||
+                label.contains("CPU");
+    }
+
+    private static void printPackageLoadDetails(long[][] initialTicks, long[][] newTicks,List<CentralProcessor.LogicalProcessor> group,Cpu cpuOne) {
+        // 初始化各类型总增量
+        long totalUser = 0, totalNice = 0, totalSystem = 0, totalIdle = 0;
+        long totalIowait = 0, totalIrq = 0, totalSoftirq = 0, totalSteal = 0;
+        long totalAll = 0;
+
+        // 计算该物理CPU组内所有逻辑处理器的增量总和
+        for (CentralProcessor.LogicalProcessor lp : group) {
+            int processorNumber = lp.getProcessorNumber();
+            long[] initial = initialTicks[processorNumber];
+            long[] current = newTicks[processorNumber];
+
+            totalUser += current[CentralProcessor.TickType.USER.getIndex()] - initial[CentralProcessor.TickType.USER.getIndex()];
+            totalNice += current[CentralProcessor.TickType.NICE.getIndex()] - initial[CentralProcessor.TickType.NICE.getIndex()];
+            totalSystem += current[CentralProcessor.TickType.SYSTEM.getIndex()] - initial[CentralProcessor.TickType.SYSTEM.getIndex()];
+            totalIdle += current[CentralProcessor.TickType.IDLE.getIndex()] - initial[CentralProcessor.TickType.IDLE.getIndex()];
+            totalIowait += current[CentralProcessor.TickType.IOWAIT.getIndex()] - initial[CentralProcessor.TickType.IOWAIT.getIndex()];
+            totalIrq += current[CentralProcessor.TickType.IRQ.getIndex()] - initial[CentralProcessor.TickType.IRQ.getIndex()];
+            totalSoftirq += current[CentralProcessor.TickType.SOFTIRQ.getIndex()] - initial[CentralProcessor.TickType.SOFTIRQ.getIndex()];
+            totalSteal += current[CentralProcessor.TickType.STEAL.getIndex()] - initial[CentralProcessor.TickType.STEAL.getIndex()];
+        }
+
+        // 计算总时间
+        totalAll = totalUser + totalNice + totalSystem + totalIdle +
+                totalIowait + totalIrq + totalSoftirq + totalSteal;
 
         System.out.println("详细负载百分比:");
 
         // 计算并显示每个负载类型的百分比(保留两位小数)
-        if (total > 0) {
-            System.out.printf("  User:   %.2f%%\n", 100.0 * user / total);
-            System.out.printf("  Nice:   %.2f%%\n", 100.0 * nice / total);
-            System.out.printf("  System: %.2f%%\n", 100.0 * system / total);
-            System.out.printf("  Idle:   %.2f%%\n", 100.0 * idle / total);
-            System.out.printf("  IOWait: %.2f%%\n", 100.0 * iowait / total);
-            System.out.printf("  IRQ:    %.2f%%\n", 100.0 * irq / total);
-            System.out.printf("  SoftIRQ:%.2f%%\n", 100.0 * softirq / total);
-            System.out.printf("  Steal:  %.2f%%\n", 100.0 * steal / total);
-            cpuOne.setSys(Arith.round(100.0 * system / total, 2));
-            cpuOne.setFree(Arith.round(100.0 * idle / total, 2));
-            cpuOne.setUsed(Arith.round(100.0 * user / total, 2));
+        if (totalAll > 0) {
+            System.out.printf("  User:   %.2f%%\n", 100.0 * totalUser / totalAll);
+            System.out.printf("  Nice:   %.2f%%\n", 100.0 * totalNice / totalAll);
+            System.out.printf("  System: %.2f%%\n", 100.0 * totalSystem / totalAll);
+            System.out.printf("  Idle:   %.2f%%\n", 100.0 * totalIdle / totalAll);
+            System.out.printf("  IOWait: %.2f%%\n", 100.0 * totalIowait / totalAll);
+            System.out.printf("  IRQ:    %.2f%%\n", 100.0 * totalIrq / totalAll);
+            System.out.printf("  SoftIRQ:%.2f%%\n", 100.0 * totalSoftirq / totalAll);
+            System.out.printf("  Steal:  %.2f%%\n", 100.0 * totalSteal / totalAll);
+            cpuOne.setSys(Arith.round(100.0 * totalSystem / totalAll, 2));
+            cpuOne.setFree(Arith.round(100.0 * totalIdle / totalAll, 2));
+            cpuOne.setUsed(Arith.round(100.0 * totalUser / totalAll, 2));
         } else {
             System.out.println("  无有效负载数据");
         }
     }
 
-    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;
+    private static double calculatePackageLoad(long[][] initialTicks, long[][] newTicks, List<CentralProcessor.LogicalProcessor> group) {
+        long totalUsed = 0;
+        long total = 0;
 
+        for (CentralProcessor.LogicalProcessor lp : group) {
+            int processorNumber = lp.getProcessorNumber();
+            long[] initial = initialTicks[processorNumber];
+            long[] current = newTicks[processorNumber];
+
+            // 计算该逻辑处理器的负载增量
+            long user = current[CentralProcessor.TickType.USER.getIndex()] - initial[CentralProcessor.TickType.USER.getIndex()];
+            long nice = current[CentralProcessor.TickType.NICE.getIndex()] - initial[CentralProcessor.TickType.NICE.getIndex()];
+            long system = current[CentralProcessor.TickType.SYSTEM.getIndex()] - initial[CentralProcessor.TickType.SYSTEM.getIndex()];
+            long idle = current[CentralProcessor.TickType.IDLE.getIndex()] - initial[CentralProcessor.TickType.IDLE.getIndex()];
+            long iowait = current[CentralProcessor.TickType.IOWAIT.getIndex()] - initial[CentralProcessor.TickType.IOWAIT.getIndex()];
+            long irq = current[CentralProcessor.TickType.IRQ.getIndex()] - initial[CentralProcessor.TickType.IRQ.getIndex()];
+            long softirq = current[CentralProcessor.TickType.SOFTIRQ.getIndex()] - initial[CentralProcessor.TickType.SOFTIRQ.getIndex()];
+            long steal = current[CentralProcessor.TickType.STEAL.getIndex()] - initial[CentralProcessor.TickType.STEAL.getIndex()];
+
+            totalUsed += user + nice + system + irq + softirq + steal;
+            total += totalUsed + idle + iowait;
+        }
         return total > 0 ? (double) totalUsed / total : 0;
     }