一:背景
1. 講故事
最近幾天接到了幾個crash的求助,可能這幾個朋友沒玩過怎麼去生成dump,只能手把手教,感覺也不是一個辦法,所以有必要總結一下,後續再有朋友諮詢的話,我就可以把這篇文章丟過去了???,好了,我大概總結了下面三種方式:
-
procdump -e
-
procdump -> AEDebug
-
Windows Error Reporting
老讀者應該知道,我一直都推崇 procdump 去搞定這些事情,畢竟它是一款可跨平臺抓取的強大靈巧工具。
二: 實現可測試案例
從 dump 樣本來看,web類的程式是最多的,所以這裡我就以 Asp.NET MVC 5
作為案例,在 RouteConfig 類中我使用一個Timer不斷的丟擲異常,目的就是把 w3wp 程式給弄掛掉,參考程式碼如下:
public class RouteConfig
{
public static Timer timer;
public static void RegisterRoutes(RouteCollection routes)
{
timer = new Timer(new TimerCallback(m =>
{
var r = 10 / Convert.ToInt32("0");
}), null, 60000, 5000);
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
對了,肯定有朋友問:為什麼不在 Action 中拋異常,這是因為 Http管道
會把這種異常包裝成 http 500,所以就達不到 crash 的效果了。
接下來把程式部署到 IIS 上並執行,可以清楚的看到 Windows 事件檢視器
中成功的記錄到了崩潰資訊,如下圖所示:
三: 3種抓取方式解析
1. 使用 procdump -e
這種方式簡單但不太穩定,因為有幾個朋友告訴我,procdump在抓取的過程中報錯了,原因是程式已退出,不管怎麼說這個要看你運氣了哈,這裡的 -e
是 exception
的簡寫,具體可參見官方文件: https://docs.microsoft.com/zh-cn/sysinternals/downloads/procdump。
-e Write a dump when the process encounters an unhandled exception. Include the 1 to create dump on first chance exceptions.
完整的參考命令如下:
C:\Windows\system32>procdump -e -ma -w w3wp E:\test
ProcDump v10.0 - Sysinternals process dump utility
Copyright (C) 2009-2020 Mark Russinovich and Andrew Richards
Sysinternals - www.sysinternals.com
Waiting for process named w3wp...
...
Press Ctrl-C to end monitoring without terminating the process.
[21:12:08] Exception: 04242420
[21:12:08] Exception: E0434352.CLR
[21:12:09] Exception: E0434352.CLR
[21:12:09] Exception: E0434352.CLR
[21:12:09] Exception: E0434352.CLR
[21:12:09] Exception: E0434352.CLR
[21:12:09] Exception: E0434352.CLR
[21:12:14] Exception: C0000094.INT_DIVIDE_BY_ZERO
[21:12:14] Unhandled: C0000094.INT_DIVIDE_BY_ZERO
[21:12:14] Dump 1 initiated: E:\test\w3wp.exe_210525_211214.dmp
[21:12:14] Dump 1 writing: Estimated dump file size is 326 MB.
[21:12:15] Dump 1 complete: 326 MB written in 1.2 seconds
[21:12:15] Dump count reached.
從輸出資訊看已經成功抓取了 dump 檔案,如果你的機器有多個 w3wp,可以將其替換成 pid,參考命令如下:
C:\Windows\system32>procdump -e -ma 9320 E:\test
2. 將 procdump 作為 AeDebug 的預設偵錯程式
它的大概運作原理是:當程式出現了未處理異常,此時會啟用作業系統的 Win32 unhandled exception filter
,這個過濾器會呼叫登錄檔中 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
節點配置的偵錯程式,也就是我的 Procdump,要將 procdump 送到登錄檔的 AeDebug 節點,可以使用 -i
進行註冊。
-i Install ProcDump as the AeDebug postmortem debugger. Only -ma, -mp, -d and -r are supported as additional options.
完整參考命令如下:
C:\Windows\system32>procdump -ma -i E:\test
ProcDump v10.0 - Sysinternals process dump utility
Copyright (C) 2009-2020 Mark Russinovich and Andrew Richards
Sysinternals - www.sysinternals.com
Set to:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
(REG_SZ) Auto = 1
(REG_SZ) Debugger = "C:\xcode\soft\Procdump\procdump.exe" -accepteula -ma -j "E:\test" %ld %ld %p
Set to:
HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug
(REG_SZ) Auto = 1
(REG_SZ) Debugger = "C:\xcode\soft\Procdump\procdump.exe" -accepteula -ma -j "E:\test" %ld %ld %p
ProcDump is now set as the Just-in-time (AeDebug) debugger.
從輸出資訊看已經成功將其送入到登錄檔了,接下來可以開啟 登錄檔編輯器
去驗證。
最後就是把 web 跑起來,1min之後就會成功的看到 E:\test
下的 dump 檔案啦,截圖如下:
從圖中看有2個dump,具體為什麼是2個我就不管了,就怕不生成。???
3. 藉助 Windows Error Reporting 生成
它的大概運作原理是藉助 windows 自帶的 Windows Error Reporting
服務去幫助我們生成程式的 crash dump,要實現的話,必須開啟這個服務並且在登錄檔中配置好你要抓取的exe程式,配置起來有點繁瑣,這裡有一個bat指令碼,直接執行即可,簡單粗暴。
SET DMPPATH=E:\test
SC CONFIG WerSvc START= AUTO
NET START WerSvc
ECHO 啟用完成
REG DELETE HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger /f
REG DELETE HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\DbgManagedDebugger /f
REG DELETE HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger /f
REG DELETE HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\DbgManagedDebugger /f
ECHO 刪除完成
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe" /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe" /t REG_SZ /v DumpFolder /d %DMPPATH% /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe" /t REG_DWORD /v DumpCount /d 2 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe" /t REG_DWORD /v DumpType /d 2 /f
ECHO 啟用完成
PAUSE
有3個引數需要簡單解釋一下。
- DumpFolder: dump的存放路徑
- DumpCount: 最多保留幾個 dump 檔案
- DumpType: 0:Custom dump. 1:Mini dump. 2:Full dump
bat執行完成後,可以到登錄檔中驗證一下。
接下來把web跑起來,1min之後你就會看到生成的dump檔案了,截圖如下:
三:總結
對於抓取程式crash的dump,這三種方式基本上就可以做到萬無一失,總結完後,對你對我都是節省寶貴的時間???。
更多高質量乾貨:參見我的 GitHub: dotnetfly