在進程崩潰的時候自動抓取一個DUMP文件
在如下的情況下需要使用這樣的技巧:
1. 生產環境上出問題, 我們需要抓取dump文件, 在線下去debug.
2. 正在運行一大堆測試, 當其中一個崩潰的時候, 不希望在運行時干擾整個測試動作, 僅需要收集一些測試信息.
3. 問題在連接到debugger後無法重現.
簡單來說, 就是你希望在對環境影響最小的前提下, 抓取儘可能多的信息.
爲了滿足這種需求, 最好的方式是配置 just-in-time (JIT) debugger , 讓它在進程崩潰的任何時候能夠: 啓動, 抓取dump, 退出.
JIT debugger的基本思想是:當一個進程崩潰的時候,加載debugger, attach debugger到進程上, 以便我們弄清楚爲什麼會崩潰.
有註冊表鍵值可以提供這項基本的功能, 針對託管的, 非託管的都有. 如果你的應用程序是用託管代碼編寫的, 你也許會問, "我的應用程序是託管代碼, 爲什麼我要關心native code?" 即使是給你最基本的託管代碼應用程序都會運行native code, 如果你的需求是收集任何crash的數據, 你將需要爲這兩種類型的代碼設置註冊表鍵值. 在CLR第四版中, 已經定義了帶有native code的託管JIT debugger. 然而, 這個修改並不影響我這裏的指導, 這裏, V2 V4都適用.
我如何配置debugger?
=====================
1. 下載並安裝最新的“Debugging Tools for Windows.”
a. 如果你是在運行64-bit OS, 你將會需要32-Bit and 64-bit 兩個版本.
b. 你在機器上既可以安裝整個的工具集(這很快, 安裝很小), 或者你可以在一臺機器上安裝, 然後從安裝路徑拷貝"cdb.exe"到任何目標機器上.
注意, 下面的sample.reg文件假設你安裝32位debugger到c:/debuggers/x86/下, 64位debugger到c:/debuggers/x64/ 下
2. 創建或配置下面的註冊表鍵和值(如果你使用的是64位版的windows, 你還需要在Wow6432節點下配置這些值)
a. 鍵: HKLM/Software/Microsoft/Windows NT/Current Version/AeDebug:
i. 值: "Debugger"
1. 類型: String
2. 值數據: -pv -p %ld -c “.dump /u /ma ;.kill;qd"
ii. 值: “Auto”
1. 類型: String
2. 值數據: "1"
b. 鍵: HKLM/Software/Microsoft/.NETFramework
i. 值: “DbgManagedDebugger"
1. 類型: String
2. 值數據: -pv -p %ld -c ".dump /u /ma ;.kill;qd"
ii. 值: "DbgJITDebugLaunchSetting"
1. 類型: DWORD(32-bit)
2. 值數據: 2
注意: 你應該根據合適的debugger的位數, 比如說, 你想要OS/CLR爲64位進程崩潰加載64位的debugger, 32位的進程崩潰加載32爲的debugger. 請確保你的debugger的路徑是被正確地設置了的.
下面的sample.reg文件會配置機器上的cdb.exe爲自動加載, 並在每個進程崩潰的時候生成一個crash dump文件. 注意文件中的關於debugger路徑和dump文件存放路徑的假設.
Windows Registry Editor Version 5.00
;This reg file installs just-in-time debuggers to capture a dump of all process
;crashes for the machine.
;
;Assumes 32-bit debugger is cdb.exe and is installed to c:/debuggers/x86/.
;Assumes 64-bit debugger is cdb.exe and is installed to c:/debuggers/x64/.
;
;Assumes crash dumps can be written to c:/crash_dumps/.
;Make sure all users have write access to this directory.
[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework]
"DbgManagedDebugger"="/"c://debuggers//x64//cdb.exe/" -pv -p %ld -c /".dump /u /ma c://crash_dumps//crash.dmp;.kill;qd/""
"DbgJITDebugLaunchSetting"=dword:00000002
[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/AeDebug]
"Debugger"="/"c://debuggers//x64//cdb.exe/" -pv -p %ld -c /".dump /u /ma c://crash_dumps//crash.dmp;.kill;qd/""
"Auto"="1"
;The following keys are only used on 64-bit versions of Windows (note Wow6432Node).
;They can be safely created with no side-effects on 32-bit versions of Windows.
;Alternatively, you can delete the remainder of this file if you’re running a
;32-bit version of Windows.
[HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/Windows NT/CurrentVersion/AeDebug]
"Debugger"="/"c://debuggers//x86//cdb.exe/" -pv -p %ld -c /".dump /u /ma c://crash_dumps//crash.dmp;.kill;qd/""
"Auto"="1"
[HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/.NETFramework]
"DbgManagedDebugger"="/"c://debuggers//x86//cdb.exe/" -pv -p %ld -c /".dump /u /ma c://crash_dumps//crash.dmp;.kill;qd/""
"DbgJITDebugLaunchSetting"=dword:00000002
這些鍵值有什麼作用?
=====================
“Debugger” 和“DbgManagedDebugger” 的值數據基本上就是在進程崩潰的時候運行的命令行(printf格式的字符串). OS 或者 CLR 用實際值替代掉其中的格式指示符, 然後使用當前用戶的崩潰進程的上下文來運行命令. 比如說, 會用崩潰的process id去替換掉 "%ld".
在命令行中, 我指定了:
加載cdb.exel, 也就是debugger
很顯然, 你必須爲debugger指定正確的路徑
“-pv %ld” : 非侵入性地(僅僅是把線程暫停)掛接到崩潰的進程上(操作系統或CLR會實質上地幫你添寫PID)
“.dump /u /ma ”: 拿下完整的內存dump, 使用一個獨一無二的名字(使用日期, 時間, 和進程ID來擴展名稱), 把它保存到指定的路徑
路徑和文件名可以是任何你想指定的形式. 因爲debugger是在崩潰的進程的上下文中加載的, 所以你要確保你指定的路徑是任何用戶都有權限寫入的
“.kill”: 幹掉目標進程, 因爲你已經得到了你需要的數據.
“qd”: 離開debugger
“Auto” 和“DbgJITDebugLaunchSetting”的值設定了何時加載debugger的策略規則(policy). 正如我上面寫道的, 我們希望儘快地得到數據, 並繼續, 所以我們不希望用戶干預的介入. 比如說, 在一個服務器上, 可能不會有人登錄並點擊什麼OK按鈕. 我描述的配置會自動地爲機器上的所有進程加載註冊了的debugger, 而不會彈出框來讓你選擇(參考Enabling JIT-attach Debugging, 其中有關於彈這個框的更多信息). 注意, 當這些配置存在了之後, 機器上運行的所有進程在崩潰的時候都會自動地加載起debugger, 從而不會讓你有機會去在"Windows Error Reporting"裏呈交這個crash.
我不在乎一臺機器上的絕大多數的進程, 我可以只抓取某一個進程的crash dump麼?
====================
這個問題的答案取決於你OS的版本, 還有CLR的版本. 下面是規則:
對於native code來說: 你的OS必須是Vista/Server 2008 或者更高.
對於managed code來說: 你的CLR的版本必須是V4(或者更高)
下面是如何配置的方法:
1. 如同上面的2.a.i 和2.b.i一樣, 配置debugger鍵值. (AeDebug/Debugger 和.NETFramework/DbgManagedDebugger)
2. 確保AeDebug/Auto 和.NETFramework/DbgJITDebugLaunchSetting 已經被配置爲自動加載(再一次強調, 參考Enabling JIT-attach Debugging 來查找更多信息).
a. 或者你可以刪除它們Or you can delete them.
3. 創建如下的註冊表鍵值對Create the following registry keys and values:
a. HKLM/Software/Microsoft/Windows/Windows Error Reporting/DebugApplications
i. 值: (e.g. “myapp.exe”)
1. 類型: DWORD (32-bit)
2. 值數據: 1
b. 爲每一個你希望debugger自動加載的應用程序重複這個操作.
如果你更喜歡個人的控制, 你可以配置HKCU中的DebugApplications 鍵值對. 當這些配置生效的時候, debugger會僅爲你指定的進程加載起來, 而其他進程所使用的會是普通的錯誤處理方式(比如說, 最默認的配置下, 會彈出一個框, 讓你提交這個錯誤到微軟去.)
下面的例子中的sample.reg文件, 會配置cdb.exe爲自動加載的, 但僅僅是爲HelloWorld.exe. 你可以替代HelloWorld.exe爲你想要抓取dump的進程.
Windows Registry Editor Version 5.00
;This reg file installs just-in-time debuggers to capture a dump of only the
;processes listed under the [DebugApplications] key, below.
;
;Assumes 32-bit debugger is cdb.exe and is installed to c:/debuggers/x86/.
;Assumes 64-bit debugger is cdb.exe and is installed to c:/debuggers/x64/.
;
;Assumes crash dumps can be written to c:/crash_dumps/.
;Make sure all users have write access to this directory.
[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework]
"DbgManagedDebugger"="/"c://debuggers//x64//cdb.exe/" -pv -p %ld -c /".dump /u /ma c://crash_dumps//crash.dmp;.kill;qd/""
"DbgJITDebugLaunchSetting"=dword:00000000
[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/AeDebug]
"Debugger"="/"c://debuggers//x64//cdb.exe/" -pv -p %ld -c /".dump /u /ma c://crash_dumps//crash.dmp;.kill;qd/""
"Auto"="0"
;The following keys are only used on 64-bit versions of Windows (note Wow6432Node).
;They can be safely created with no side-effects on 32-bit versions of Windows.
;Alternatively, you can delete the remainder of this file if you’re running a
;32-bit version of Windows.
[HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/Windows NT/CurrentVersion/AeDebug]
"Debugger"="/"c://debuggers//x86//cdb.exe/" -pv -p %ld -c /".dump /u /ma c://crash_dumps//crash.dmp;.kill;qd/""
"Auto"="0"
[HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/.NETFramework]
"DbgManagedDebugger"="/"c://debuggers//x86//cdb.exe/" -pv -p %ld -c /".dump /u /ma c://crash_dumps//crash.dmp;.kill;qd/""
"DbgJITDebugLaunchSetting"=dword:00000000
;For each application you want the debugger to be auto-launched, add a row below
;similar to “HelloWorld.exe"=dword:00000001 but replacing HelloWorld.exe with
;your application .exe name.
[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/Windows Error Reporting/DebugApplications]
"HelloWorld.exe"=dword:00000001
除了抓dump, 我還可以做更多的事情麼?
=========================
關於Windows Debugger是的命令行開關的更多的信息, 可以在Debugging Tools fow Windows中包括的文檔中找到. 你並沒有被限制僅僅抓取dump, 你還可以執行很多debugger的自動化操作呢.
嗯, 那麼究竟是什麼導致了問題發生?
========================
現在, 你已經有了dump文件, 是時候來弄清楚爲什麼應用程序崩潰了. 對於那些已經熟悉了dump debugging的讀者, 到這裏你就拉出WinDBG + SOS(託管debugging的擴展組件), 並深入研究了. 但是請等一下! 如果你的應用程序運行在CLR V4上(.Net Framework 4.0), 你可以在Visual Studio 2010中進行debug了. 我們的目標是在VS2010中, debug dump像live debug一樣的體驗(如同走到了斷點).
針對如何debug託管代碼的crash, 搜索"managed dump debugging"會返回不少結果. 一個很好的初學者去處是Tess Ferrandez’s blog (一個微軟的技術支持大牛). 她有不少關於這個話題的精彩文章, 包括dump debugging in VS 2010, 還有一些實驗, 手把手的文章.
Automatically Capturing a Dump When a Process Crashes
http://blogs.msdn.com/clrteam/archive/2009/10/15/automatically-capturing-a-dump-when-a-process-crashes.aspx
Enabling JIT-attach Debugging
http://msdn.microsoft.com/en-us/library/2ac5yxx6(VS.80).aspx
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.