zoukankan      html  css  js  c++  java
  • 在进程崩溃的时候自动抓取一个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. 值数据: <path to cdb> -pv -p %ld -c “.dump /u /ma <dump file path\name.dmp>;.kill;qd"

                       ii. 值:  “Auto”

                                   1. 类型: String

                                   2. 值数据: "1"

            b. 键: HKLM\Software\Microsoft\.NETFramework

                       i. 值: “DbgManagedDebugger"

                                   1. 类型: String

                                   2. 值数据: <path to cdb> -pv -p %ld -c ".dump /u /ma <dump file path\name.dmp>;.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 file path\name.dmp>”: 拿下完整的内存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. 值: <Name of application executable> (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

  • 相关阅读:
    让层遮挡select(ie6下的问题)
    HTTP协议详解(真的很经典)
    网络编辑基础:对HTTP协议的头信息详解
    (OK) MIMP
    (OK) MIMP
    (OK) MIMP
    (OK)(OK) Android-x86-7.1.1/ kernel 4.4.62
    (OK)(OK) Android-x86-7.1.1/ kernel 4.4.62
    (OK) Android-x86-7.1.1/ kernel 4.4.62
    (OK)(OK) Android-x86-7.1.1/ kernel 4.4.62
  • 原文地址:https://www.cnblogs.com/awpatp/p/1681101.html
Copyright © 2011-2022 走看看