You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Serilog多进程共享失效:.NET 8 Core API无法写入同一错误日志文件

问题排查:多.NET 8 API共享Serilog文件日志失败

问题现象

  • 两个.NET 8 Core API(API-1、API-2)配置Serilog将错误日志写入同一Errors-.txt文件,但始终只有第一个触发错误的API能成功写入,另一个完全无法生成日志。
  • 测试1:重启IIS后先触发API-1错误,日志写入成功;API-2触发错误无日志输出;API-1再次触发错误仍能正常写入。
  • 测试2:重启IIS后先触发API-2错误,日志写入成功;API-1触发错误无日志输出;API-2再次触发错误仍能正常写入。

当前配置

API-1的Serilog配置(appsettings.json)

"Serilog": {
  "MinimumLevel": {
    "Default": "Information",
    "Override": {
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "System": "Warning"
    }
  },
  "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
  "WriteTo": [
    { "Name": "Console" },
    {
      "Name": "File",
      "Args": {
        "path": "E:/Logs/SerilogAPITester1-.txt",
        "rollingInterval": "Day",
        "fileSizeLimitBytes": 50000000,
        "rollOnFileSizeLimit": true,
        "shared": true
      }
    },
    {
      "Name": "File",
      "Args": {
        "path": "E:/Logs/Errors-.txt",
        "rollingInterval": "Day",
        "fileSizeLimitBytes": 50000000,
        "rollOnFileSizeLimit": true,
        "shared": true,
        "restrictedToMinimumLevel": "Error"
      }
    }
  ]
}

API-2的配置差异

仅修改两处:

"AppName": "Tester1" --> "Tester2"
"path": "E:/Logs/SerilogAPITester1-.txt" --> "E:/Logs/SerilogAPITester2-.txt"

Program.cs初始化代码

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(builder.Configuration).CreateLogger();

排查与解决方案

1. 升级Serilog.Sinks.File版本

旧版本的Serilog.Sinks.File在多进程共享文件场景下存在锁竞争缺陷,.NET 8环境建议直接升级到v5.0.0及以上稳定版,该版本修复了多进程文件写入的锁机制问题,是解决此类问题的核心步骤。

2. 验证日志目录权限

  • 确认E:/Logs目录对两个API的IIS应用程序池身份(通常为IIS AppPool\对应的应用池名称)同时拥有读写权限,权限不足会导致后启动的API无法打开日志文件。
  • 滚动日志生成的带日期后缀文件(如Errors-20240520.txt)也需要确保权限继承正常。

3. 补充滚动日志清理配置(可选但推荐)

在共享文件的sink配置中添加retainedFileCountLimit,避免日志滚动清理时因锁冲突导致写入失败:

{
  "Name": "File",
  "Args": {
    "path": "E:/Logs/Errors-.txt",
    "rollingInterval": "Day",
    "fileSizeLimitBytes": 50000000,
    "rollOnFileSizeLimit": true,
    "shared": true,
    "restrictedToMinimumLevel": "Error",
    "retainedFileCountLimit": 30
  }
}

4. 启用Serilog内部日志排查

在Program.cs中添加内部日志输出,直接查看文件写入时的错误细节(如锁失败、权限报错):

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(builder.Configuration)
    .WriteTo.Sink(new Serilog.Sinks.File.FileSink(
        "E:/Logs/SerilogInternal-.txt",
        new Serilog.Formatting.Display.MessageTemplateTextFormatter("{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}", null),
        fileSizeLimitBytes: 50000000,
        rollOnFileSizeLimit: true,
        shared: true,
        retainedFileCountLimit: 10
    ), restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Verbose)
    .CreateLogger();

触发错误后检查SerilogInternal-.txt,即可定位具体失败原因。

5. 验证shared配置是否加载成功

确认shared: true被正确读取,可在Program.cs中添加调试代码:

var errorSinkArgs = builder.Configuration
    .GetSection("Serilog:WriteTo")
    .Where(w => w.GetValue<string>("Name") == "File")
    .Select(w => w.GetSection("Args"))
    .First(a => a.GetValue<string>("path") == "E:/Logs/Errors-.txt");
Console.WriteLine($"Error sink shared setting: {errorSinkArgs.GetValue<bool>("shared")}");

如果输出为false,说明配置未被正确解析,需检查JSON格式或配置加载逻辑。

总结

最核心的问题大概率是Serilog.Sinks.File版本过低导致的多进程锁冲突,优先升级包版本,再结合权限检查和内部日志排查,即可解决日志写入异常问题。

内容的提问来源于stack exchange,提问作者MCS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:32:31