在進程崩潰的時候自動抓取一個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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章