181 lines
8.2 KiB
Java
181 lines
8.2 KiB
Java
package com.sshmanager.controller;
|
||
|
||
import com.sshmanager.entity.Connection;
|
||
import com.sshmanager.entity.User;
|
||
import com.sshmanager.repository.UserRepository;
|
||
import com.sshmanager.service.ConnectionService;
|
||
import com.sshmanager.service.SshService;
|
||
import org.springframework.http.ResponseEntity;
|
||
import org.springframework.security.core.Authentication;
|
||
import org.springframework.web.bind.annotation.*;
|
||
|
||
import java.util.HashMap;
|
||
import java.util.Map;
|
||
|
||
@RestController
|
||
@RequestMapping("/api/monitor")
|
||
public class MonitorController {
|
||
|
||
private final ConnectionService connectionService;
|
||
private final SshService sshService;
|
||
private final UserRepository userRepository;
|
||
|
||
public MonitorController(ConnectionService connectionService, SshService sshService, UserRepository userRepository) {
|
||
this.connectionService = connectionService;
|
||
this.sshService = sshService;
|
||
this.userRepository = userRepository;
|
||
}
|
||
|
||
private Long getCurrentUserId(Authentication auth) {
|
||
User user = userRepository.findByUsername(auth.getName()).orElseThrow(() -> new IllegalStateException("User not found"));
|
||
return user.getId();
|
||
}
|
||
|
||
@GetMapping("/{connectionId}")
|
||
public ResponseEntity<Map<String, Object>> getServerMetrics(@PathVariable Long connectionId, Authentication authentication) {
|
||
try {
|
||
Long userId = getCurrentUserId(authentication);
|
||
Connection conn = connectionService.getConnectionForSsh(connectionId, userId);
|
||
if (conn == null) {
|
||
return ResponseEntity.notFound().build();
|
||
}
|
||
|
||
String password = connectionService.getDecryptedPassword(conn);
|
||
String privateKey = connectionService.getDecryptedPrivateKey(conn);
|
||
String passphrase = connectionService.getDecryptedPassphrase(conn);
|
||
|
||
Map<String, Object> metrics = new HashMap<>();
|
||
|
||
// 获取CPU使用率(兼容多种系统)
|
||
try {
|
||
double cpuUsage = 0;
|
||
try {
|
||
// 优先使用top
|
||
String cpuOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"top -bn1 2>/dev/null | grep 'Cpu(s)' | sed 's/.*, *\\([0-9.]*\\)%* id.*/\\1/' | awk '{print 100 - $1}'");
|
||
if (!cpuOutput.trim().isEmpty()) {
|
||
cpuUsage = Double.parseDouble(cpuOutput.trim());
|
||
} else {
|
||
throw new Exception("top command failed");
|
||
}
|
||
} catch (Exception e) {
|
||
// 备用方案:使用/proc/stat计算(需要两次采样,这里简化处理用vmstat)
|
||
try {
|
||
String vmstatOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"vmstat 1 2 | tail -1 | awk '{print 100 - $15}'");
|
||
cpuUsage = Double.parseDouble(vmstatOutput.trim());
|
||
} catch (Exception e2) {
|
||
throw new Exception("Both top and vmstat failed");
|
||
}
|
||
}
|
||
metrics.put("cpuUsage", Math.round(cpuUsage * 10.0) / 10.0);
|
||
} catch (Exception e) {
|
||
metrics.put("cpuUsage", null);
|
||
}
|
||
|
||
// 获取内存信息(兼容多种系统)
|
||
try {
|
||
long totalMem = 0;
|
||
long usedMem = 0;
|
||
try {
|
||
// 优先使用free -b
|
||
String memOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"free -b 2>/dev/null | grep Mem");
|
||
if (!memOutput.trim().isEmpty()) {
|
||
String[] memParts = memOutput.trim().split("\\s+");
|
||
if (memParts.length >= 3) {
|
||
totalMem = Long.parseLong(memParts[1]);
|
||
usedMem = Long.parseLong(memParts[2]);
|
||
}
|
||
}
|
||
} catch (Exception e) {
|
||
// 备用方案:从/proc/meminfo读取
|
||
String meminfoOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"cat /proc/meminfo | grep -E 'MemTotal|MemAvailable'");
|
||
String[] lines = meminfoOutput.trim().split("\n");
|
||
if (lines.length >= 2) {
|
||
totalMem = Long.parseLong(lines[0].replaceAll("\\D+", "")) * 1024;
|
||
long availableMem = Long.parseLong(lines[1].replaceAll("\\D+", "")) * 1024;
|
||
usedMem = totalMem - availableMem;
|
||
}
|
||
}
|
||
|
||
if (totalMem > 0 && usedMem >= 0) {
|
||
double memUsage = (double) usedMem / totalMem * 100;
|
||
metrics.put("memTotal", totalMem);
|
||
metrics.put("memUsed", usedMem);
|
||
metrics.put("memUsage", Math.round(memUsage * 10.0) / 10.0);
|
||
} else {
|
||
throw new Exception("Failed to parse memory info");
|
||
}
|
||
} catch (Exception e) {
|
||
metrics.put("memTotal", null);
|
||
metrics.put("memUsed", null);
|
||
metrics.put("memUsage", null);
|
||
}
|
||
|
||
// 获取磁盘使用率
|
||
try {
|
||
String diskOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"df -P / | tail -1");
|
||
String[] diskParts = diskOutput.trim().split("\\s+");
|
||
int diskUsage = Integer.parseInt(diskParts[4].replace("%", ""));
|
||
metrics.put("diskUsage", diskUsage);
|
||
} catch (Exception e) {
|
||
metrics.put("diskUsage", null);
|
||
}
|
||
|
||
// 获取系统负载
|
||
try {
|
||
String loadOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"cat /proc/loadavg");
|
||
String[] loadParts = loadOutput.trim().split("\\s+");
|
||
double load1 = Double.parseDouble(loadParts[0]);
|
||
metrics.put("load1", load1);
|
||
} catch (Exception e) {
|
||
metrics.put("load1", null);
|
||
}
|
||
|
||
// 获取CPU核数
|
||
try {
|
||
String cpuCountOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"grep -c ^processor /proc/cpuinfo");
|
||
int cpuCores = Integer.parseInt(cpuCountOutput.trim());
|
||
metrics.put("cpuCores", cpuCores);
|
||
} catch (Exception e) {
|
||
metrics.put("cpuCores", null);
|
||
}
|
||
|
||
// 获取系统运行时间
|
||
try {
|
||
String uptimeOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"uptime -p");
|
||
metrics.put("uptime", uptimeOutput.trim().replace("up ", ""));
|
||
} catch (Exception e) {
|
||
// 尝试另一种uptime格式
|
||
try {
|
||
String uptimeOutput = sshService.executeCommand(conn, password, privateKey, passphrase,
|
||
"cat /proc/uptime | awk '{print $1}'");
|
||
double uptimeSeconds = Double.parseDouble(uptimeOutput.trim());
|
||
long days = (long) (uptimeSeconds / 86400);
|
||
long hours = (long) ((uptimeSeconds % 86400) / 3600);
|
||
long minutes = (long) ((uptimeSeconds % 3600) / 60);
|
||
StringBuilder uptimeStr = new StringBuilder();
|
||
if (days > 0) uptimeStr.append(days).append("d ");
|
||
if (hours > 0) uptimeStr.append(hours).append("h ");
|
||
uptimeStr.append(minutes).append("m");
|
||
metrics.put("uptime", uptimeStr.toString().trim());
|
||
} catch (Exception e2) {
|
||
metrics.put("uptime", null);
|
||
}
|
||
}
|
||
|
||
return ResponseEntity.ok(metrics);
|
||
} catch (Exception e) {
|
||
Map<String, Object> error = new HashMap<>();
|
||
error.put("error", e.getMessage());
|
||
return ResponseEntity.badRequest().body(error);
|
||
}
|
||
}
|
||
}
|