feat : 어플리케이션 동작유무 감지 및 재실행 로직 추가

master
Kurt92 4 months ago
parent 9239ee0520
commit 244394d55f

@ -3,12 +3,14 @@ package com.manual.controller;
import com.worker.scheduler.smg.schedule.SinmungoInOutScheduler;
import com.worker.scheduler.update.schedule.WarSyncScheduler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@Slf4j
@RestController
@RequiredArgsConstructor
public class RunController {
@ -16,6 +18,7 @@ public class RunController {
private final WarSyncScheduler warSyncScheduler;
private final SinmungoInOutScheduler sinmungoInOutScheduler;
@PostMapping("/menual/update-war")
public ResponseEntity<?> updateWar() throws IOException {
@ -37,6 +40,15 @@ public class RunController {
sinmungoInOutScheduler.sinmungoAnswerSendScheduler();
return ResponseEntity.ok("Success");
}
@PostMapping("/menual/restart-parking-app")
public ResponseEntity<?> restartParkingApp() throws IOException {
// 클린파킹 수동 실행
return ResponseEntity.ok("Success");
}
}

@ -75,37 +75,92 @@ public class WarSyncScheduler {
log.info("[배포] SFTP 업테이트 서버 연결 성공");
// 리모트 파일 속성
// todo : 데브환경 분기처리
SftpATTRS attrs = null;
if(activeProfile.equals("prod")){
String ftpDir;
SftpATTRS attrs;
if (activeProfile.equals("prod")) {
attrs = sftp.lstat(REMOTE_CC_WAR_PATH);
ftpDir = REMOTE_CC_WAR_PATH;
} else {
attrs = sftp.lstat(REMOTE_CC_WAR_DEV_PATH);
ftpDir = REMOTE_CC_WAR_DEV_PATH;
}
log.info("--- " + activeProfile + " ---");
long remoteSize = attrs.getSize();
int remoteMtime = attrs.getMTime();
// 메타파일 비교
boolean isUpdated = isWarUpdated(remoteSize, remoteMtime);
log.info("[배포] 변경감지");
log.info("[배포] 변경감지: " + isUpdated);
// 변경 없을 때도 실행 상태 확인
if (!isUpdated) {
log.info("[배포] 변경 없음. 스킵");
log.info("[배포] 변경 없음. 실행 상태 확인");
boolean needRun = true;
if (Files.exists(PID_FILE_PATH)) {
long pid = Long.parseLong(Files.readString(PID_FILE_PATH).trim());
boolean isAlive = ProcessHandle.of(pid).map(ProcessHandle::isAlive).orElse(false);
if (isAlive) {
String cmdline = "";
try {
cmdline = Files.readString(Path.of("/proc/" + pid + "/cmdline"));
} catch (IOException ignored) {}
if (cmdline.contains("cc-server")) { // ← 실제 WAR 명칭으로 변경
log.info("[배포] 프로세스는 살아 있고 동일 앱입니다. 스킵");
needRun = false;
} else {
log.warn("[배포] PID 살아있지만 다른 앱입니다. PID 제거");
Files.deleteIfExists(PID_FILE_PATH);
}
} else {
log.warn("[배포] PID 살아있지 않음. 제거 후 재실행");
Files.deleteIfExists(PID_FILE_PATH);
}
}
if (needRun) {
log.info("[배포] 앱 실행 중 아님. 기존 WAR로 재실행");
runWar();
log.info("[배포] 재실행 완료 (변경 없음)");
}
return;
}
// 변경 있음 → 배포 절차 실행
// 다운로드
try (InputStream in = sftp.get(REMOTE_CC_WAR_PATH)) {
try (InputStream in = sftp.get(ftpDir)) {
Files.copy(in, LOCAL_TMP_PATH, StandardCopyOption.REPLACE_EXISTING);
log.info("[배포] SFTP 다운로드 완료");
}
// 실행 중이면 종료
killPreviousWar();
log.info("[배포] 프로세스 kill");
// 킬하고 기존에 war를 백업으로 이동해야함
// 롤백을 위함.
if (Files.exists(PID_FILE_PATH)) {
long pid = Long.parseLong(Files.readString(PID_FILE_PATH).trim());
boolean isAlive = ProcessHandle.of(pid).map(ProcessHandle::isAlive).orElse(false);
if (isAlive) {
String cmdline = "";
try {
cmdline = Files.readString(Path.of("/proc/" + pid + "/cmdline"));
} catch (IOException ignored) {}
if (cmdline.contains("cc-server")) {
killPreviousWar();
log.info("[배포] 기존 프로세스 종료 완료");
} else {
log.warn("[배포] PID 살아있지만 다른 앱. PID 제거");
Files.deleteIfExists(PID_FILE_PATH);
}
} else {
log.warn("[배포] PID 존재하나 죽어있음. 제거");
Files.deleteIfExists(PID_FILE_PATH);
}
}
// 교체
Files.move(LOCAL_TMP_PATH, LOCAL_WAR_PATH, StandardCopyOption.REPLACE_EXISTING);
@ -128,6 +183,7 @@ public class WarSyncScheduler {
}
}
// 변경 체크 (파일 사이즈, 수정시간)
private boolean isWarUpdated(long remoteSize, int remoteMtime) throws IOException {
if (!Files.exists(META_FILE_PATH)) return true;
@ -169,4 +225,8 @@ public class WarSyncScheduler {
Files.writeString(PID_FILE_PATH, String.valueOf(process.pid()));
log.info("[배포] 새 PID 저장: " + process.pid());
}
private boolean isProcessAlive(long pid) {
return ProcessHandle.of(pid).map(ProcessHandle::isAlive).orElse(false);
}
}

Loading…
Cancel
Save