Serilog运行时删除日志文件后无法重建,如何强制其重新创建日志文件?
问题根因
- 你的日志写入逻辑存在错误:
Log.CloseAndFlush()是程序终止前用来释放日志资源的方法,不能每次写完日志就调用。调用该方法后全局Log.Logger实例会被标记为已释放,后续所有写入操作都会直接失效,这是你删除文件后无法写入的核心原因之一。 - Serilog.File Sink默认会持有日志文件的独占句柄,手动删除日志文件后,Sink无法感知到文件已被删除,仍然会向已失效的句柄写入内容,不会主动创建新文件。
解决方案
方案1(推荐):修复写法+添加自动重建参数
首先删掉每次写日志后的Log.CloseAndFlush()调用,该方法仅需在程序完全退出前执行一次。同时在File Sink配置中添加recreateOnMissing: true参数,该参数专门用于处理日志文件被外部删除后自动重建的场景。
修改后完整代码如下:
public static class Logger { // 程序启动时调用一次即可,无需重复初始化 public static void ConfigureSerilog() { var logFile = Path.Combine(Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData), "OSync\\OSync.log"); Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.File(logFile, rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 2097152, retainedFileCountLimit: 7, // 新增参数:文件被删除后自动重建 recreateOnMissing: true) .CreateLogger(); } public static void Write(LogEventLevel logEvent, string message) { Log.Write(logEvent, message); // 若需要实时落盘可以在这里调用Log.Flush(),不要调用CloseAndFlush } // 程序退出时调用一次即可 public static void CloseLogger() { Log.CloseAndFlush(); } }
如果你的Serilog.Sinks.File版本较低没有recreateOnMissing参数,直接将该Nuget包升级到最新版即可。
方案2:写入前校验文件状态动态重置
如果不想升级依赖包,可以在写入日志前判断日志文件是否存在,不存在就重新初始化Logger,适合低版本兼容场景:
public static class Logger { // 提前缓存日志路径避免重复拼接 private static readonly string _logPath = Path.Combine(Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData), "OSync\\OSync.log"); public static void ConfigureSerilog() { Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.File(_logPath, rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 2097152, retainedFileCountLimit: 7) .CreateLogger(); } public static void Write(LogEventLevel logEvent, string message) { // 文件不存在就重新初始化Logger if (!File.Exists(_logPath)) { ConfigureSerilog(); } Log.Write(logEvent, message); } }
注意该方案需要自行处理多线程并发问题,避免多个线程同时重置Logger导致异常。
内容的提问来源于stack exchange,提问作者BElluu
相关产品推荐
相关产品推荐

