【问题标题】:NLog - Why aren't locked files released once Shutdown is called?NLog - 为什么在调用 Shutdown 后不释放锁定的文件?
【发布时间】:2020-02-05 19:34:31
【问题描述】:

我了解 NLog 的 LogManager.Shutdown() 可以有效地删除所有日志记录项并停止日志记录。在此之后以编程方式删除锁定的日志文件应该可以,但我发现它并没有立即被删除,文件仍然被锁定,只有在进程结束后才会解锁。

这是我的程序化配置:

            var fileTarget = new FileTarget()
            {
                FileName = "logs.txt",
                Layout = <string layout>,
                KeepFileOpen = true,
                ArchiveAboveSize = 50000000,
                ArchiveEvery = FileArchivePeriod.Day,
                ArchiveNumbering = ArchiveNumberingMode.DateAndSequence,
                ArchiveDateFormat = DatePattern
            };

            var asyncFileTarget =
                new NLog.Targets.Wrappers.AsyncTargetWrapper(fileTarget, 10000, NLog.Targets.Wrappers.AsyncTargetWrapperOverflowAction.Block);
            asyncFileTarget.Name = "async_target";

            var config = new LoggingConfiguration();
            config.AddTarget(asyncFileTarget);
            config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, asyncFileTarget);

如果我这样做了,

    LogManager.Shutdown(); //logs get flushed and written to the file
    File.Delete("logs.txt"); //Nothing happens, file deletes only after process exits

我也试过

    LogManager.Configuration = null;

结果相同。

出于性能原因,我需要 KeepFileOpen = true。 如何让 NLog 释放锁定的目标文件?

【问题讨论】:

  • 什么是 NLog 版本?内部日志中记录的内容(跟踪级别) - 请参阅 github.com/nlog/nlog/wiki/Internal-logging 以启用
  • 我不知道这是否有帮助。文档说(强调我的):“keepFileOpen - 指示是否保持日志文件打开而不是在每个日志记录事件上打开和关闭它。将此属性更改为 true 将大大提高性能,但也会保持文件句柄锁定。启用此选项时考虑设置 openFileCacheTimeout = 30,因为它将允许归档操作并对被删除的日志文件做出反应。"
  • 根据源码LogManager.Shutdown只是清除配置;它实际上并没有关闭任何东西。如果你还有fileTarget的引用,你可以在告诉Nlog关闭后手动关闭。

标签: c# logging nlog delete-file


【解决方案1】:

我最好的猜测是 nLog(我不熟悉)正在另一个线程上运行。我不确定您对多线程有多熟悉,但这意味着 File.Delete(Logs.txt) 代码可以在 LogManager 有机会完成关闭之前执行。

也许尝试在某些异步函数上使用 await 关键字?也许这会有所帮助?

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/async

或者,如果 nLog 具有像“IsBusy”或“isRunning”这样的函数/指示符 - 您总是可以使用 while 循环(在您调用关闭之后)?

粗略的例子:

       while (nLog.isBusy)
       {
            // Sleep while we wait for the isBusy status to change
            System.Threading.Thread.Sleep(100); 
       }

【讨论】:

    【解决方案2】:

    当您检查 NLog 的源代码时,您会看到关闭将关闭所有目​​标。在 CloseTarget 的 Filetarget 中。这将删除 FileAppenders 中的锁。

    我创建了一个非常小的示例来展示它的工作原理。你可以看到它here in Github。使用 NLog 4.6.8。

    演示部分:

    static void Main(string[] args)
    {
        const string fileName = "C:/temp/logs.txt";
    
        var config = CreateLogConfig(fileName);
        LogManager.Configuration = config;
    
        Console.WriteLine("Write logs");
        var myLogger = LogManager.GetLogger("myLogger");
        myLogger.Info("Hi from my logger!");
    
        LogManager.Flush();// flush to check if really locked. You could disable this and it still works.
    
        WriteConsoleFileExistsAndLockInfo(fileName);
    
        Console.WriteLine("Shutdown NLog");
        LogManager.Shutdown(); //logs get flushed and written to the file
    
        WriteConsoleFileExistsAndLockInfo(fileName);
        Console.WriteLine($"File content: {File.ReadAllText(fileName)}");
        Console.WriteLine($"Full path: {new FileInfo(fileName).FullName}");
        Console.WriteLine("Deleting file ...");
        File.Delete(fileName);
        Console.WriteLine("Deleted file");
        WriteConsoleFileExistsAndLockInfo(fileName);
    }
    

    输出:

    如果它仍然无法在您的站点上运行,请检查 NLog's internal log: &lt;nlog internalLogFile="c:\log.txt" internalLogLevel="Trace"&gt;

    当然,也可能是另一个进程正在锁定您的文件。也许是杀毒软件?

    【讨论】:

    • 谢谢!我会在启用 Trace 的情况下试试这个,希望能找到我所缺少的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多