只有累積,沒有奇蹟

顯示具有 IIS 標籤的文章。 顯示所有文章
顯示具有 IIS 標籤的文章。 顯示所有文章

2023年9月18日 星期一

[NETCore] ASP.NET Core 啟動失敗 - 嘗試存取通訊端被拒絕,因為存取權限不足

問題 
接獲同事詢問專案無法正常啟用,專案是使用 ASP.NET Core 2.2 開發並搭配 Kestrel 使用,在過去開發時都正常運作但今天忽然就遭遇啟動異常的狀況,在啟用時會跳出錯誤訊息為 'Unable to bind to http://localhost:5000 on the IPv4 loopback interface: '嘗試存取通訊端被拒絕,因為存取權限不足。''  ,這篇文章就針對此問題的解決方式做分享若是有不清楚或是錯誤的地方歡迎討論予糾正

異常現場
異常發生時畫面如下
Log 中紀錄的詳細錯誤訊息如下
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\user\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
      Unable to bind to http://localhost:5000 on the IPv4 loopback interface: '嘗試存取通訊端被拒絕,因為存取權限不足。'.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
      Unable to bind to http://localhost:5000 on the IPv6 loopback interface: '嘗試存取通訊端被拒絕,因為存取權限不足。'.
crit: Microsoft.AspNetCore.Server.Kestrel[0]
      Unable to start Kestrel.
System.IO.IOException: Failed to bind to address http://localhost:5000. ---> System.AggregateException: One or more errors occurred. (嘗試存取通訊端被拒絕,因為存取權限不足。) (嘗試存取通訊端被拒絕,因為存取權限不足。) ---> System.Net.Sockets.SocketException: 嘗試存取通訊端被拒絕,因為存取權限不足。
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransport.BindAsync()
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<>c__DisplayClass21_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions.BindAsync(AddressBindContext context)
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions.BindAsync(AddressBindContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.BindAsync(AddressBindContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IServerAddressesFeature addresses, KestrelServerOptions serverOptions, ILogger logger, Func`2 createBinding)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)

C:\Program Files\dotnet\dotnet.exe (process 31468) exited with code -1.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . . 
根據錯誤訊息提供的線索,異常原因可能是因為 Kestrel 在啟動時失敗造成 (Startup failure),Kestrel 預設是使用 5000 port,懷疑該已被占用造成啟用時使用該 port 號卻無法正常執行,才跳出 嘗試存取通訊端被拒絕,因為存取權限不足 錯誤訊息,首先先來釐清推測是否正確,查詢 port 使用狀況可以透過以下兩種方式

命令提示字元
開啟 Windows Terminal 使用命令提示字元,輸入  netstat -nat | findstr 5000  指令查看 port 使用狀況 
PS C:\> netstat -nat | findstr 5000 
查詢後可以看到目前系統中 5000 port 已被占用

TCPView
TCPView 是一個非常實用的小工具,可以顯示目前系統中 TCP 與 UDP 連接的狀態,不用在命令提示字元下指令就可以看到需要的資訊,之前用過此工具幫忙在 Production 解決不少問題,如果之前未使用過強烈建議可以下載使用看看,在微軟官方就有提供下載連結 : 傳送門,解完壓縮之後直接執行 TCPView.exe 執行檔,可以看到 5000 Port 已被其他應用程式所占用

解決方案
透過上述步驟可以看到,主要原因是因為 Kestrel 所要用的 Port 已被其他應用程式所佔用,占用的應用程式 ProcessID 是 4,可以透過以下幾種方式解決

設定 IIS
在過去的經驗中告訴我們 system ProcessID 為 4 時候 87% 是 IIS,推測可能是因為在 IIS 中某一個 Application 中有設定使用到該機器的 5000 Port,可以開啟 IIS 檢查在建立 Application 所設定到的 Port 號,有與 5000 衝突的部分替換為新的 Port 號即可,果然在同事的電腦中發現測是的應用程式已將指定 Port 占用,調整後 ASP.NET Core 專案即可正常運行。

設定 Kestrel 
另外一種方式是調整 Kestrel 的指定 Port,在 ASP.NET Core 預設是使用 5000 port,如果電腦中應用程式的 5000 Port 是無法調整的,及可以透過設定的方式將預設的 Port 改用其他指定 port 避免衝突的狀況發生,如果是使用 ASP.NET Core Web template 建立專案,其中  CreateDefaultBuilder  方法會呼叫 serverOptions.Configure(context.Configuration.GetSection("Kestrel")) 載入設定,因此我們可以到 appsettings.json 調整,以下列設定為例是將 Kestrel port 指定為 5050
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5050"
      }
    }
  }, 
  ....other settings
} 
以上兩種方式都可以解決當 Kestrel 預設 Port 被占用,造成應用程式啟動失敗的問題,各位看官可以依據情境選擇適合是自己的解決方案,若是有更好的方法也歡迎提出來一起討論,Thanks & Happy Coding :)

參考
ASP.NET Core 中的 Kestrel 網頁伺服器實作

2019年6月13日 星期四

[Tool] Log Parser Studio - 搜尋 Log 好幫手

前言
這幾天專案遇到些小亂流,必須找到特定條件的應用程式 Log 做資料的確認及重送機制,雖然系統有使用 ELK但由於專案太舊導致 Log 沒紀錄在 ELK 上面,為了快速找到多台應用程式中的 Log 資訊,在搜尋過程中爬 Log 使用 Log Parser 工具來快速搜尋 Log 資訊,避免過度花費人工的方式逐一進行搜尋 Log,這篇文章就針對 Log Paresr Studio 工具做簡單的介紹與說明,若有問題歡迎提出一起討論或是給予指導。

安裝
Log Parser 是一套強大的文字搜尋工具,可以針對單一或是多個 Log 檔案進行搜尋,支援多種 常見的Log 類型,最新版為 Log Parser 2.2 可以在微軟官網下載 : 傳送門 ,安裝後開啟應用程式如下
可以輸入 command line 指定關鍵字與資料夾進行搜尋,舉例來說我想要在 C:\ Filemon 檔案搜尋 Access Denied 關鍵字,可以輸入下面指令取得
LOGPARSER "Select Text from C:\Filemon.log where Text like '%Access Denied%'" -i:TEXTLINE -q:Off
輸入後按下執行會跳出下列
// 搜尋的結果

Statistics
Elements processed: 640444
Elements output:    1
Execution time:     12.75 seconds 
如果對於使用指令搜尋有興趣,可以嘗試看看常用搜尋指令 : Log Parser Rocks! More than 50 Examples!

Log Parser Studio
我自己在使用上都是用 Log Parser Studio 工具,對於在使用上懶人會較為方便一些,Log Parser Studio 下載位置 : 傳送門,下載完畢開啟應用程式如下
首頁會顯示常用的查詢 Lib 語法,可以提供使用者快速進行搜尋的動作,如果要自訂搜尋的話可以透過下列方式

設定 Log
在一開始使用前需要設定要搜尋的 Log 位置,設定步驟如下
步驟如下

  • Step 1 : 新增 Query 
  • Step 2 : 開啟要查詢的 Log 檔案或是資料夾位置
  • Step 3 : 新增檔案
  • Step 4 : 設定完成

  • 查詢
    設定要搜尋的 Log 來源後 (單一檔案或是多個檔案) , 接著就是要使用最重要的搜尋功能,在 Log Parser Studio 工具下方可以輸入搜尋語法,主要搜尋欄位為 Text,以下例子為找 Log 中含有關鍵字 'Service -Start' 字眼的 Log 內容
    步驟如下

  • Step 1 : 選擇要查詢的 Log Type 
  • Step 2 : 在下方搜尋區塊輸入要找的關鍵字內容
  • Step 3 : 按下搜尋,查詢結果區塊就會顯示符合的內容

  • 匯出
    在 Log Parser Studio 中提供將查詢的結果匯出的功能,點擊左上角 File > export,選擇要輸出的檔案類型
    以上透過簡單的情境介紹了 Log Parser Studio 的基本使用方式,如果想要了解更多內容的話,可以透過作者的詳細介紹文章跟進階情境使用方式,來讓自己更熟悉這套強大的軟體

  • Getting started with Log Parser Studio
  • Getting started with Log Parser Studio, part 2
  • Getting started with Log Parser Studio, part 3
  • 希望可以透過以上簡單說明,讓你有知道有這麼好用的工具可以使用,也可以省下人工爬 Log 的困擾,如果下次有搜尋 Log 的需求時,不妨也可以考慮看看用 Log Parser Studio :)

    2019年5月14日 星期二

    [NETCore] ASP.NET Core 啟動異常 - HTTP Error 500.30 - ANCM In-Process Start Failure

    問題 
    在開發專案時跳出異常訊息,錯誤訊息為  HTTP Error 500.30 - ANCM In-Process Start Failure 這篇就針對此案例作簡單紀錄與分享若是有不清楚或是錯誤的地方歡迎討論予糾正

    解決方法 
    廢話不多說,先看案發現場的錯誤畫面
    執行異常的程式代碼,看起來很單純的代碼
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }
    
    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
               
    
    在錯誤訊息中提到應用程式無法啟動可能是因為 Application 啟動失敗、或是啟動時發生異常造成,建議解決方案為開啟事件檢視器進行確認,因此照著建議的除錯步驟找出問題的發生點

    事件檢視器
    開啟事件檢視器發現啟動 Application 時有多筆異常原因,過濾後有幫助的訊息如下
    可以看到事件檢視器錯誤訊息為  Application '/LM/W3SVC/2/ROOT' with physical root 'D:\Marcus\git\SerilogWebAppLab\SerilogWebAppLab\SerilogWebAppLab\' hit unexpected managed exception, exception code = '0xe0434352'. Please check the stderr logs for more information. ,其中提到 exception code 為 0xe0434352,在 How do I fix a .NET windows application crashing at startup with Exception code: 0xE0434352 文章中提到此錯誤代碼為 .NET 在執行中異常的代碼,因此錯誤訊息也建議透過 stderr 紀錄來查看更多訊息 (一直挖挖蒐集麵包屑的概念),接著下一步是確認 stderr 相關 Log 紀錄。

    ASP.NET Core Module stdout log
    在 ASP.NET Core 中 stdout log 預設是關閉的,可以透過 Web.config 設定  stdoutlogEnable  開啟,如下
    <aspNetCore processPath="dotnet"
          arguments=".\MyApp.dll"
          stdoutLogEnabled="true"
          stdoutLogFile=".\logs\stdout"
          hostingModel="InProcess"> 
    stdoutLogEnabled 為啟用 stdout 紀錄,stdoutLogFile 是設定輸出 Log 路徑。如果是使用 Visual Studio IDE 使用 IIS Express 執行的話,則可以到專案檔底下的隱藏資料夾中的 applicationhost.config 搜尋 aspNetCore 區塊設定
    ProjectName\.vs\ProjectName\config\applicationhost.config
    修改後儲存 Web.config 檔案,重新執行一次應用程式,可以看到專案底下 Log 資料夾有新增指定檔案
    檔名前面為 stdout 開頭,後面為時間戳記及處理事件代碼
    stdout_20190513222912_28664.log
    開啟 Log 檔案,內容顯示無法 Application 啟動時異常原因
    透過 stdout Log 得知異常原因為 CreateDefaultBuilder 方法時預設會去讀取 appsettings.json 檔案,但由於 json 檔案格式錯誤造成 application 啟動時無法正常啟動,因而顯示 HTTP error 500.30 的狀況發生,修正後即可正常執行,宣告除蟲成功 ! 

    備註 : Troubleshoot ASP.NET Core on IIS 內文有提到因為沒有限制記錄檔大小或是數量上限,啟用可能會造成應用程式或是伺服器失敗,請在確認完畢後關閉  stdoutlogEnable  為 false。

    Improve 
    調整代碼在啟動時加上 try catch 記錄錯誤訊息,讓之後遇到同樣事情可以更快發現 :)
    public class Program
    {
        public static void Main(string[] args)
        {
            InitialSerilog();
    
            try
            {
                CreateWebHostBuilder(args).Build().Run();
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
                throw;
            }
        }
    
        private static void InitialSerilog()
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .WriteTo.Console()
                .WriteTo.File("logs/log_.txt", rollingInterval: RollingInterval.Day)
                .CreateLogger();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

    參考

    Copyright © m@rcus 學習筆記 | Powered by Blogger

    Design by Anders Noren | Blogger Theme by NewBloggerThemes.com