aspnetcore進程內托管的坑-非常規方法解決Log4Net不寫日志的問題


問題描述:Log4Net,本地測試一切正常,發布后,無法自動創建文件夾和日志文件,無法寫入文件。

一、在項目中配置Log4Net

請參考我的上一篇博客 《aspnetcore配置log4net並添加全局異常處理》,常規做法。

二、Log4Net不寫日志常規解決步驟

一般講來,Log4Net是非常成熟的框架,很難出現問題,出現不寫日志這種情況,首先要做的是檢查我們的代碼、配置是否正確。

  1. 檢查目錄中是否包含 log4net.config ,如果文件不存在,手動復制一份即可。
  2. 檢查  log4net.config 文件,主要是日志文件輸出路徑,一般日志保存目錄是這樣的  根目錄/Logs/Errors/xxxx.log ,其他資料里一般寫法為  <file value="Logs\\Errors\\" /> ,在這里個人推薦這樣來寫  <file value="Logs/Errors/" /> ,原因是曾經在  ubuntu > nginx  環境下部署時,第一種寫法無法正常工作,改為第二種方法后正常。
  3. 檢查文件夾權限,確保具有寫權限。

三、絕望的排查過程

因為在本地測試完全正常,所以代碼和配置文件應該沒有問題,但保險起見,還是將網上常用的幾種寫法都嘗試了一遍,然而,並沒有什么卵用。

接下來,查看文件夾權限,講真,對於Server的文件系統我是真的了解很少,大部分時間遇到權限問題,就簡單的給Everyone一個讀寫權限了事。不出意外的,折騰許久,還是失敗了。

重復以上步驟兩個小時后...

 頭昏腦漲中,想起之前的項目中使用Log4Net是正常的,寫法和部署方式一樣,為什么這次不行呢?

於是對比之前的項目,把IIS中站點和應用程序池的配置項一條一條拿出來看,一個小時后...

完全一樣啊,啥情況,要不換NLog???雖然為了項目進度換成其他框架也說的過去,但作為程序員,明知道有bug卻解決不了,總歸過不去心里這一關不是。不甘心啊~

四、靈光乍現

就在准備把問題先放放,修改項目使用Nlog的時候,鬼使神差的,去看了眼任務管理器,咦~~還真發現了問題,之前的項目都是開了三個進程(w3wp.exe \ conhost.exe \ dotnet.exe),而新項目只有兩個(w3wp.exe \ conhost.exe),精神立馬振奮了一下,看來問題可能就在這里了。打開項目的  web.config  文件,發現多了點東西:

有問題找度娘,搜索 InProcess ,大部分內容都一樣,沒看出啥問題,難道是我想錯了,問題不在這里?說臟話會不會發布失敗?咱也不知道咱也不敢問,還是憋回去吧!

抱着最后一絲希望,跑到官方文檔 《ASP.NET Core 模塊》,不得不說啊,微軟自動翻譯的文檔真的很考驗中文水平,但是再爛也得看不是,這塊內容之前也沒說關注過,不管能不能解決問題,看看也好,當補課了。

細細看下來,有這么一段

在 ASP.NET Core 2.2.1 或早期版本中,GetCurrentDirectory 會返回 IIS 啟動的進程的工作目錄而非應用目錄(例如,對於 w3wp.exe,是 C:\Windows\System32\inetsrv)。

對於設置應用的當前目錄的示例代碼,請參閱 CurrentDirectoryHelpers 類。 調用 SetCurrentDirectory 方法。 后續 GetCurrentDirectory 調用提供應用的目錄。

醍醐灌頂,雖然外面已經是傍晚時分,但我眼前仿佛一道曙光升起,恍惚間似乎看到天女降臨,嘿,嘿嘿~~

五、填坑

 接下來就簡單了,github上把CurrentDirectoryHelpers類搞下來,在  startup.cs  的構造函數中添加  CurrentDirectoryHelpers.SetCurrentDirectory(); ,重新發布、部署、啟動站點,文件出現了。

下面貼一下  CurrentDirectoryHelpers  的實現,不要謝我,我只是代碼的搬運工

using System;

namespace SampleApp
{
    internal class CurrentDirectoryHelpers
    {
        internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        [System.Runtime.InteropServices.DllImport(AspNetCoreModuleDll)]
        private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);

        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        private struct IISConfigurationData
        {
            public IntPtr pNativeApplication;
            [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
            public string pwzFullApplicationPath;
            [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
            public string pwzVirtualApplicationPath;
            public bool fWindowsAuthEnabled;
            public bool fBasicAuthEnabled;
            public bool fAnonymousAuthEnable;
        }

        public static void SetCurrentDirectory()
        {
            try
            {
                // Check if physical path was provided by ANCM
                var sitePhysicalPath = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_PHYSICAL_PATH");
                if (string.IsNullOrEmpty(sitePhysicalPath))
                {
                    // Skip if not running ANCM InProcess
                    if (GetModuleHandle(AspNetCoreModuleDll) == IntPtr.Zero)
                    {
                        return;
                    }

                    IISConfigurationData configurationData = default(IISConfigurationData);
                    if (http_get_application_properties(ref configurationData) != 0)
                    {
                        return;
                    }

                    sitePhysicalPath = configurationData.pwzFullApplicationPath;
                }

                Environment.CurrentDirectory = sitePhysicalPath;
            }
            catch
            {
                // ignore
            }
        }
    }
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM