Serilog:不使用RollingFile时如何实现旧日志自动删除
解决方案:单次执行专属日志+自动清理旧日志
方案1:自定义日志清理逻辑(最直接可控)
在应用启动或执行结束阶段,主动遍历日志目录,按文件创建时间或数量删除旧日志。这种方式不依赖日志框架的特殊功能,完全由你掌控清理时机和规则。
示例代码(Java):
import java.io.File; import java.util.Arrays; import java.util.Comparator; public class LogCleaner { // 保留指定数量的最新日志,删除其余旧日志 public static void cleanOldLogs(String logDir, int retainCount) { File dir = new File(logDir); if (!dir.exists() || !dir.isDirectory()) { return; } // 筛选符合命名规则的日志文件(比如app-20240520-143022.log) File[] logFiles = dir.listFiles(file -> file.getName().matches("app-\\d{8}-\\d{6}\\.log")); if (logFiles == null || logFiles.length <= retainCount) { return; } // 按最后修改时间倒序排序,最新的在前 Arrays.sort(logFiles, Comparator.comparingLong(File::lastModified).reversed()); // 删除超出保留数量的旧日志 for (int i = retainCount; i < logFiles.length; i++) { if (!logFiles[i].delete()) { // 可选:记录删除失败日志 System.err.println("Failed to delete old log: " + logFiles[i].getAbsolutePath()); } } } }
使用方式:
- 在应用初始化时调用:
LogCleaner.cleanOldLogs("./logs", 10);(保留最近10个日志文件) - 或者在执行结束前调用,确保清理完成后再退出应用。
方案2:扩展日志框架的FileAppender实现自动清理
如果希望把清理逻辑和日志配置绑定,可以继承日志框架的FileAppender,在Appender初始化时自动执行清理。以Log4j2为例:
自定义Appender代码:
import org.apache.logging.log4j.core.appender.FileAppender; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginFactory; @Plugin(name = "CleaningFileAppender", category = "Core", elementType = "appender", printObject = true) public class CleaningFileAppender extends FileAppender { private final int retainCount; private final String logDir; protected CleaningFileAppender(Builder builder) { super(builder); this.retainCount = builder.retainCount; // 从日志文件名中提取目录路径 this.logDir = builder.fileName.substring(0, builder.fileName.lastIndexOf('/')); // 初始化时自动清理旧日志 cleanOldLogs(); } private void cleanOldLogs() { LogCleaner.cleanOldLogs(logDir, retainCount); } public static class Builder extends FileAppender.Builder<Builder> { @PluginAttribute("retainCount") private int retainCount = 10; public Builder retainCount(int retainCount) { this.retainCount = retainCount; return this; } @Override public CleaningFileAppender build() { return new CleaningFileAppender(this); } } @PluginFactory public static Builder newBuilder() { return new Builder(); } }
Log4j2配置文件(log4j2.xml):
<Configuration status="WARN"> <Appenders> <CleaningFileAppender name="CleaningFile" fileName="logs/app-${date:yyyyMMdd-HHmmss}.log" retainCount="10"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </CleaningFileAppender> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="CleaningFile"/> </Root> </Loggers> </Configuration>
这样每次应用启动初始化日志Appender时,会自动清理超出数量的旧日志。
方案3:借助操作系统定时任务批量清理
如果不想修改应用代码,可以用系统定时任务定期清理日志目录。这种方式适合多实例部署或跨应用的日志统一管理场景。
Linux(Cron)示例:
- 编写清理脚本
clean_logs.sh:
#!/bin/bash LOG_DIR="/opt/app/logs" RETAIN_COUNT=10 # 按修改时间倒序列出日志文件,跳过前N个,删除剩余的 ls -t "$LOG_DIR"/app-*.log 2>/dev/null | tail -n +$((RETAIN_COUNT + 1)) | xargs rm -f
- 添加可执行权限:
chmod +x clean_logs.sh - 配置Cron,每天凌晨2点执行:
crontab -e # 添加以下内容 0 2 * * * /opt/app/clean_logs.sh
Windows(任务计划程序)示例:
编写批处理脚本clean_logs.bat:
@echo off set LOG_DIR=C:\app\logs set RETAIN_COUNT=10 :: 按修改时间排序,保留最新N个,删除旧日志 for /f "skip=%RETAIN_COUNT% tokens=*" %%f in ('dir /b /o-d %LOG_DIR%\app-*.log') do ( del "%LOG_DIR%\%%f" )
然后在任务计划程序中创建定时任务,定期执行该批处理脚本。
内容的提问来源于stack exchange,提问作者Yosi Maurer
相关产品推荐
相关产品推荐

