Windows服务中的Serilog无法写入日志文件

34

我在一个TopShelf服务中使用Serilog记录日志并输出到控制台和一个滚动的文件。当我在控制台中运行服务时,我的消息被写入日志文件,但是当我安装并运行服务时,没有任何日志记录。请问我需要进行特殊的配置吗?该文件被写入到二进制文件夹下的“.\logs\log-{date}.txt”中。


我也遇到了同样的问题,你有找到解决方案的机会吗? - Michael
8个回答

50
我遇到了一个非常类似的问题。在我的情况下,问题出在相对路径上。 我只需要指定绝对路径。现在它完美地工作了。
WriteTo.RollingFile(
  AppDomain.CurrentDomain.BaseDirectory + "\\logs\\log-{Date}.log"
)

2
<appSettings> 配置中,您还可以在路径中使用环境变量,例如 %TEMP% - 将日志放在 %APPDATA% 或类似位置可能效果很好。 - Nicholas Blumhardt
AppDomain.CurrentDomain.BaseDirectory 适用于 NET 5-6-7 吗? - Kiquenet

15
我们遇到了同样的问题,这是我们找到的解决方法:
  • Serilog配置为滚动日志文件并写入Seq。
  • Serilog启用了持久日志。

症状

  • 没有创建日志文件。
  • 没有将日志写入Seq。

根据@gdoten的评论,我们的日志文件实际上是被写入到\windows\syswow64目录下(服务以localservice身份运行)。

我们认为这些文件的权限可能不允许持久化缓冲文件被读取,导致无法将日志写入Seq。

修复/解决方法是将滚动日志文件和缓冲路径进行硬编码。


1
我的实际路径是在Windows\System32目录下。 - Steven

9
 loggerFactory.AddFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log-{Date}.txt"));

试试这个方法,它在我的ASP.NET Core 2应用程序中作为Windows服务运行时有效。


我该如何在appsettings.json中指定应用程序域路径? - kudlatiger
亲爱的@kudlatiger,这是一个例子。 var myDomainPath = Configuration["domainPath"]; loggerFactory.AddFile(Path.Combine(myDomainPath, "ApiLog-{Date}.txt"));appsettings.json "domainPath": "myDomainPath", - Grigor Yeghiazaryan

4

很可能是运行服务的帐户缺少写入日志文件位置的权限。尝试将日志文件位置更改为系统的临时文件夹,看看是否是这种情况。

如果仍然失败,使用Serilog的SelfLog获取异常信息是最好的选择。


你好,尼古拉斯, 感谢您的回复。该服务正在以LocalSytem身份运行,并具有目录的完全权限(不包括特殊权限)。我目前正在使用Log4Net,因为它可以在控制台和服务中工作。但是,一旦我将Logging类更改为SeriLog,它就无法在服务中写入或创建日志文件。但在控制台模式下,它可以正常工作... o_o 我将尝试检查SelfLog,感谢您的提示! - Gope
4
我发现当我的服务记录日志时:<add key="serilog:write-to:RollingFile.pathFormat" value="ServerServiceApp-{Date}.log" />,它最终会出现在 C:\Windows\SysWOW64 目录下,这显然是服务首次启动时的当前目录。FYI。 - Glenn Doten

2
我有一个类似的问题,最初的回答是由于以下代码:

public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables()
            .Build();

这段代码指定了appsettings.json文件,并在其中设置了Serilog的配置,但是在服务中运行时,当前文件夹并不指向可执行文件所在的文件夹。因此无法找到appsettings.json文件,当然Serilog也无法按预期工作。

只需要按照以下方式更改代码即可使其正常工作。

Original Answer翻译成"最初的回答"

public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile(AppDomain.CurrentDomain.BaseDirectory + "\\appsettings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables()
            .Build();

0

我正在作为Windows服务运行,这是我的JSON文件。

{
  "Serilog": {
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "RollingFile",
        "Args": {
          "pathFormat": "C:\\Program Files\\mycomp\\myapp\\logs\\log-{Date}.txt"
        }
      }
    ],
    "Enrich": [
      "FromLogContext",
      "WithMachineName",
      "WithThreadId",
      "WithEnvironmentUserName",
      "WithProcessId"
    ],
    "Properties": {
      "Application": "MyApp",
      "Environment": "Development"
    }
  }
}


2
我在使用Windows服务和配置设置时也遇到了这个问题。结果发现问题并不是权限相关的。相反(使用上面线程中启用selflog的线索),揭示出运行时无法找到各种接收器(Console,File)的程序集。我不得不在Serilog配置中添加一个新的部分:“Using”:[“Serilog.Sinks.Console”,“Serilog.Sinks.File”,“Serilog.Enrichers.Environment”]。请参见https://github.com/serilog/serilog-settings-configuration。我不知道为什么Windows服务会影响查找程序集。 - Heems

0
我想读取appsettings.json文件并将日志文件写回应用程序目录,而不是运行服务的system32目录。从这行代码开始,这两个问题都得到了解决。

System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);

https://dev59.com/fWkv5IYBdhLWcg3wwTZm#10385563


-1

当你想要创建一个 Windows 服务和 Serilog 时,你也可以使用类似这样的代码:

var builder = new ConfigurationBuilder()
           .AddJsonFile($@"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}\appsettings.json", optional: true, reloadOnChange: true)
           .AddEnvironmentVariables();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接