|
|
@@ -13,7 +13,13 @@ import org.springframework.stereotype.Component;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.io.BufferedReader;
|
|
|
+import java.io.File;
|
|
|
import java.io.InputStreamReader;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
@Component
|
|
|
@Slf4j
|
|
|
@@ -62,9 +68,11 @@ public class AppListener implements ApplicationRunner {
|
|
|
|
|
|
// 检查目标 PID 是否存活
|
|
|
if (!checkPidExist(pid, 3, 200L)) {
|
|
|
- log.info("目标 PID 不存在,准备退出 SpringBoot 服务... pid={}", pid);
|
|
|
- shutdownApplication();
|
|
|
- break;
|
|
|
+ log.info("pid未检测到,开始检查文件");
|
|
|
+ if (!isAppAlive(fdkkLaserConfig.getBinPath() + File.separator + ".statusrc")) {
|
|
|
+ shutdownApplication();
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
log.error("PID 监听线程异常", e);
|
|
|
@@ -82,6 +90,45 @@ public class AppListener implements ApplicationRunner {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 判断应用是否存活(10秒心跳)
|
|
|
+ *
|
|
|
+ * @param filePath 心跳文件路径
|
|
|
+ * @return 存活返回 true,超时或异常返回 false
|
|
|
+ */
|
|
|
+ public static boolean isAppAlive(String filePath) {
|
|
|
+ File file = new File(filePath);
|
|
|
+
|
|
|
+ // 文件不存在,直接认为应用不存活
|
|
|
+ if (!file.exists()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ long lastModified = file.lastModified();
|
|
|
+ long currentTime = System.currentTimeMillis();
|
|
|
+
|
|
|
+ long timeout = TimeUnit.SECONDS.toMillis(3);
|
|
|
+ boolean flag = (currentTime - lastModified) <= timeout;
|
|
|
+ if (!flag) {
|
|
|
+ LocalDateTime lastTime = LocalDateTime.ofInstant(
|
|
|
+ Instant.ofEpochMilli(lastModified),
|
|
|
+ ZoneId.systemDefault()
|
|
|
+ );
|
|
|
+
|
|
|
+ String formattedTime = lastTime.format(
|
|
|
+ DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
|
|
+ );
|
|
|
+
|
|
|
+ log.error(
|
|
|
+ "心跳文件已超过 3 秒未更新,准备退出 SpringBoot 服务,文件路径:{},最后更新时间:{}",
|
|
|
+ filePath,
|
|
|
+ formattedTime
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // 超过 10 秒未更新
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 多次重试检查 PID 是否存活
|
|
|
*
|
|
|
* @param pid 进程 PID
|
|
|
@@ -108,9 +155,8 @@ public class AppListener implements ApplicationRunner {
|
|
|
* 判断 PID 是否存活(Java 8,使用系统命令)
|
|
|
*/
|
|
|
private boolean isProcessAlive(long pid) {
|
|
|
+ String pidStr = String.valueOf(pid);
|
|
|
try {
|
|
|
- String pidStr = String.valueOf(pid);
|
|
|
-
|
|
|
// 防御:PID 必须为纯数字
|
|
|
if (!pidStr.matches("\\d+")) {
|
|
|
log.error("非法 PID: {}", pidStr);
|
|
|
@@ -118,27 +164,18 @@ public class AppListener implements ApplicationRunner {
|
|
|
}
|
|
|
|
|
|
if (SystemUtil.getOsInfo().isWindows()) {
|
|
|
- // Windows 使用 tasklist,使用 ProcessBuilder 避免命令注入
|
|
|
- Process process = new ProcessBuilder("cmd", "/c",
|
|
|
- "tasklist", "/FI", "PID eq " + pidStr)
|
|
|
- .redirectErrorStream(true)
|
|
|
- .start();
|
|
|
+ // PowerShell 命令:Get-Process -Id PID
|
|
|
+ Process process = new ProcessBuilder(
|
|
|
+ "powershell",
|
|
|
+ "-Command",
|
|
|
+ "Get-Process -Id " + pidStr + " | Out-Null"
|
|
|
+ ).redirectErrorStream(true).start();
|
|
|
|
|
|
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
|
|
|
- String line;
|
|
|
- while ((line = reader.readLine()) != null) {
|
|
|
- // 简单但更精确一点的匹配方式
|
|
|
- String trimmed = line.trim();
|
|
|
- if (trimmed.isEmpty()) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- // 避免 123 和 9123 误匹配
|
|
|
- if (trimmed.matches(".*\\s" + pidStr + "\\s.*") || trimmed.endsWith(" " + pidStr)) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
+ int exitCode = process.waitFor();
|
|
|
+
|
|
|
+ // exitCode == 0 → 进程存在
|
|
|
+ // exitCode != 0 → 进程不存在
|
|
|
+ return exitCode == 0;
|
|
|
} else {
|
|
|
// Linux / Mac 使用 kill -0
|
|
|
Process process = new ProcessBuilder("kill", "-0", pidStr)
|
|
|
@@ -148,7 +185,7 @@ public class AppListener implements ApplicationRunner {
|
|
|
return exitCode == 0;
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
- log.error("检查进程存活状态失败,pid={}", pid, e);
|
|
|
+ log.error("检查进程存活状态失败,pid={}", pidStr, e);
|
|
|
return false;
|
|
|
}
|
|
|
}
|