|
|
@@ -0,0 +1,88 @@
|
|
|
+package com.zsElectric.boot.system.quartz;
|
|
|
+
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.nio.file.Paths;
|
|
|
+import java.nio.file.attribute.BasicFileAttributes;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
+import java.util.stream.Stream;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 日志文件清理定时任务
|
|
|
+ * 定期清理超过指定天数的历史日志文件
|
|
|
+ *
|
|
|
+ * @author zsElectric
|
|
|
+ * @since 2026-01-06
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+public class LogCleanupJob {
|
|
|
+
|
|
|
+ @Value("${spring.application.name:zsElectric-boot}")
|
|
|
+ private String appName;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 日志保留天数
|
|
|
+ */
|
|
|
+ private static final int LOG_RETENTION_DAYS = 30;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 日志目录
|
|
|
+ */
|
|
|
+ private static final String LOG_BASE_PATH = "/logs";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每天凌晨3点执行一次
|
|
|
+ * 清理超过30天的日志文件
|
|
|
+ */
|
|
|
+ @Scheduled(cron = "0 0 3 * * ?")
|
|
|
+ public void cleanupExpiredLogs() {
|
|
|
+ log.info("开始执行日志清理任务,清理{}天前的日志文件", LOG_RETENTION_DAYS);
|
|
|
+
|
|
|
+ Path logDir = Paths.get(LOG_BASE_PATH, appName);
|
|
|
+
|
|
|
+ if (!Files.exists(logDir)) {
|
|
|
+ log.warn("日志目录不存在: {}", logDir);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Instant cutoffTime = Instant.now().minus(LOG_RETENTION_DAYS, ChronoUnit.DAYS);
|
|
|
+ int deletedCount = 0;
|
|
|
+ int failedCount = 0;
|
|
|
+
|
|
|
+ try (Stream<Path> files = Files.list(logDir)) {
|
|
|
+ for (Path file : (Iterable<Path>) files::iterator) {
|
|
|
+ // 只处理 .log 文件,跳过当前正在写入的日志文件
|
|
|
+ String fileName = file.getFileName().toString();
|
|
|
+ if (!fileName.endsWith(".log") || fileName.equals("log.log")) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class);
|
|
|
+ Instant lastModified = attrs.lastModifiedTime().toInstant();
|
|
|
+
|
|
|
+ if (lastModified.isBefore(cutoffTime)) {
|
|
|
+ Files.delete(file);
|
|
|
+ deletedCount++;
|
|
|
+ log.debug("已删除过期日志文件: {}", fileName);
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ failedCount++;
|
|
|
+ log.error("删除日志文件失败: {}", fileName, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("读取日志目录失败: {}", logDir, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("日志清理任务执行完成,成功删除{}个文件,失败{}个", deletedCount, failedCount);
|
|
|
+ }
|
|
|
+}
|