美文网首页
iOS Crash 流程化1:一般的 Crash 日志解析方法

iOS Crash 流程化1:一般的 Crash 日志解析方法

作者: iOS亮子 | 来源:发表于2019-11-06 22:40 被阅读0次
    • iOS Crash 流程化:一般的 Crash 日志解析方法
      • TL;DR
      • 一、手动解析 Crash 日志
        • 1、需要的相关文件路径or获取途径
          • Crash Log获取
          • dSYM路径
          • Symbolicatecrash的文件(已提供)路径:
        • 2、UUID校验(确保文件之间彼此正确对应)
          • .crash
          • dSYM
          • .App
        • 3、.Crash文件分析过程
      • 二、通过Xcode查看设备崩溃信息
      • 三、使用 Apple 提供的 Crash 崩溃收集服务
        • 1、上报错误信息
        • 2、查看崩溃次数
        • 3、回到 Xcode 查看
          • 查看具体崩溃信息
      • 四、第三方崩溃分析工具 Bugly
        • 冲突
      • 补充:来自iOS知识小集
      • Ref

    默认 Build Settings -> Build Options -> Debug Information Format 中,置为了 DWARF,如果选为DWARF则不会产生dSYM文件,必须选择DWARF with dSYM File才会生成符号表文件。

    TL;DR

    1、校验Crash Log uuid

    grep "ShanLinExample arm" *.crash
    
    

    2、校验dSYM uuid

    dwarfdump --uuid ShanLinExample.App.dSYM/Contents/Resources/DWARF/ShanLinExample
    
    

    3、校验App uuid

    dwarfdump --uuid Payload/ShanLinExample.app/ShanLinExample
    
    

    4、将 Crash Log、dSYM、App 放在同一个文件夹下,符号化

    ./symbolicatecrash ShanLinExample-2016-06-14-133332.crash ShanLinExample.App.dSYM > report.log
    
    

    一、手动解析 Crash 日志

    1、需要的相关文件路径or获取途径

    Crash Log 获取
    1. 将发生了Crash的手机连接电脑,打开Xcode-菜单栏Window-Devices and Simulators

    2. 打开相应的手机View Device Logs

      image
    3. 建议按时间倒序排列,选中相应App的CrashLog,右键Export Log,以桌面CrashReport文件夹为例拷贝到~/Desktop/CrashReport

      image
    dSYM路径

    每一个打包版本都有个对应的 Archives 文件,路径为:

    ~/Library/Developer/Xcode/Archives
    
    
    1. Xcode-菜单栏Window-Archives选中相应版本Archive-show in Finder

      image
    2. 对选中.xcarchive右键显示包内容,在dSYMs文件夹下找到#AppName#.app.dSYM,拷贝到桌面CrashReport文件夹中

      image
    Symbolicatecrash的文件(已提供)路径:
    /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash
    
    

    Xcode不同版本间Symbolicatecrash的位置可能会有差异,如DVTFoundation.framework部分文件名不一样。

    若找不到可以通过命令来查找:

    find /Applications/Xcode.App -name symbolicatecrash -type f
    
    

    2、UUID校验(确保文件之间彼此正确对应)

    Ps. ShanLinExample改为对应的AppName即可。

    .crash
    grep "ShanLinExample arm" *.crash
    
    

    输出结果:

    0x100054000 - 0x1008e3fff ShanLinExample arm64  <f960888bef2430e9b844732364819642> /var/containers/Bundle/Application/84FA640D-AC63-4848-9989-9C5D8FCA748A/ShanLinExample.app/ShanLinExample
    
    
    dSYM
    dwarfdump --uuid ShanLinExample.App.dSYM/Contents/Resources/DWARF/ShanLinExample
    
    

    输出结果:

    UUID: 271C3816-D14F-3FFE-93FA-D0A8F2912DF0 (armv7) ShanLinExample.App.dSYM/Contents/Resources/DWARF/ShanLinExample
    UUID: F960888B-EF24-30E9-B844-732364819642 (arm64) ShanLinExample.App.dSYM/Contents/Resources/DWARF/ShanLinExample
    
    
    .App

    应用Archive生成的.ipa,将后缀改为.zip,解压生成Payload文件夹,里面有个与App同名文件,此时用命令行:

    dwarfdump --uuid Payload/ShanLinExample.app/ShanLinExample
    
    

    输出结果:

    UUID: 271C3816-D14F-3FFE-93FA-D0A8F2912DF0 (armv7) Payload/ShanLinExample.app/ShanLinExample
    UUID: F960888B-EF24-30E9-B844-732364819642 (arm64) Payload/ShanLinExample.app/ShanLinExample
    
    

    对比UUID即可。

    image

    3、.Crash文件分析过程

    将Symbolicatecrash、dSYM文件、.crash文件都放在一个文件夹中,例如~/Desktop/CrashReport

    先运行:

    export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
    
    

    否则会报错:

    Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 60.
    
    

    输入命令:

    ./symbolicatecrash ShanLinExample-2016-06-14-133332.crash ShanLinExample.App.dSYM > report.log
    
    

    则最终生成的report.log文件即为崩溃时的具体信息。


    二、通过Xcode查看设备崩溃信息

    可以将发生崩溃的设备连接Xcode,选择window-> devices -> 选择自己的手机 -> view device logs 就可以查看手机上所有的崩溃信息了。

    image

    只要手机上的应用是这台电脑安装打包的,这样的崩溃信息系统已经为我们符号化好了,只需要进去之后等一会就行。如果还是没有符号化完毕 ,可以选择文件,然后右击选择Re-Symbolicate就可以。

    如果是使用其他电脑进行的打包,可以在这里面将Crash文件导出,自己通过命令行的方式进行解析。


    三、使用 Apple 提供的 Crash 崩溃收集服务

    1、上报错误信息

    App上线以后苹果就会自动捕捉崩溃信息,当 App 出现 Crash 后iOS系统就会记录崩溃日志并上传到Apple的服务器。前提是需要用户同意 “与应用开发者共享”:

    设置->隐私->诊断与用量->与应用开发者共享
    
    

    2、查看崩溃次数

    上线运行一段时间后就可以登录iTunes Connect查看。登录后点击 App 分析 --> 选择要查看的App --> 点击右下角的崩溃,就可以根据筛选条件确定Crash的版本和日期。

    确定完版本和日期后并不能在iTunes Connect中查看崩溃日志。具体信息还要回到Xcode中完成。

    3、回到 Xcode 查看

    查看具体崩溃信息

    Xcode打开App,选择Window->Organizer,选择右边的Crashes

    image image image

    这里选择具体的线上版本,崩溃信息就出现了(此时需要联网)

    image

    UIKit 开头是应该是无法定位的错误,哪儿红儿哪一行就是错误信息。这里的错误实际是因为使用UIScrollview的Category进行键盘隐藏而产生的Crash。当使用中文手写键盘输入就会出现这种情况。

    可定位的错误信息如下,点击箭头选择App打开就会打开Xcode,然后把当时的线程和堆栈呈现出来。

    image image

    在项目中查看最好恢复到发布时候的版本。代码保持一致性。有时候项目中查看定位并不准确,但是有这些当时崩溃的线程,还是有助于我们定位错误的。

    注意: 官方提供的崩溃信息并不是实时的,只能查看两天之前的崩溃信息。需要实时的可以使用第三方工具。


    四、第三方崩溃分析工具 Bugly

    有很多第三方工具可以进行崩溃统计分析,个人比较推荐 Bugly(不推荐友盟,网易云捕和国外的 Crashlytics 都没有用过)。它的优势在于,可以直接将崩溃信息分析出来并且做好分类和汇总。当然完整的解析崩溃需要上传dSYMBugly后台,可以通过手动上传的方式,也可以按照 Bugly 的文档配置脚本进行上传。

    image

    这就是Bugly的页面,出错堆栈Bugly会帮我们解析好,并且会根据不同情况给一些解决建议。

    Bugly有一个页面追踪功能,这是我认为非常有用的一个功能。这个功能会将用户在不同页面之间跳转的流程记录下来。这样对于复现bug是很有用的,可以根据用户页面跳转推测出用户大概操作流程,根据这个流程复现bug

    image

    Bugly还有日报功能,可以每天汇总一篇日报,并且发到团队每个人的邮箱和微信号上。

    image

    冲突

    如果多个 Crash 收集框架存在时,往往会存在冲突。

    不管是对于 Signal 捕获还是 NSException 捕获都会存在 handler 覆盖的问题,正确的做法应该是先判断是否有前者已经注册了 handler,如果有则应该把这个 handler 保存下来,在自己处理完自己的 handler 之后,再把这个 handler 抛出去,供前面的注册者处理。这里给出相应的 Demo,Demo 由@zerygao提供。

    typedef void (*SignalHandler)(int signo, siginfo_t *info, void *context);
    
    static SignalHandler previousSignalHandler = NULL;
    
    + (void)installSignalHandler {
        struct sigaction old_action;
        sigaction(SIGABRT, NULL, &old_action);
        if (old_action.sa_flags & SA_SIGINFO) {
            previousSignalHandler = old_action.sa_sigaction;
        }
    
        LDAPMSignalRegister(SIGABRT);
        // .......
    
    }
    static void LDAPMSignalRegister(int signal) {
        struct sigaction action;
        action.sa_sigaction = LDAPMSignalHandler;
        action.sa_flags = SA_NODEFER | SA_SIGINFO;
        sigemptyset(&action.sa_mask);
        sigaction(signal, &action, 0);
    }
    static void LDAPMSignalHandler(int signal, siginfo_t* info, void* context) {
        //  获取堆栈,收集堆栈
        ........
    
        LDAPMClearSignalRigister();
    
        // 处理前者注册的 handler
        if (previousSignalHandler) {
            previousSignalHandler(signal, info, context);
        }
    }
    
    

    上面的是一个处理 Signal handler 冲突的大概代码思路,下面是 NSException handler 的处理思路,两者大同小异。

    static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler;
    
    static void LDAPMUncaughtExceptionHandler(NSException *exception) {
        // 获取堆栈,收集堆栈
        // ......
        //  处理前者注册的 handler
        if (previousUncaughtExceptionHandler) {
            previousUncaughtExceptionHandler(exception);
        }
    }
    
    + (void)installExceptionHandler {
        previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();
        NSSetUncaughtExceptionHandler(&LDAPMUncaughtExceptionHandler);
    }
    
    

    补充:来自iOS知识小集

    1、自己设备上 Xcode 编译的包发生闪退:连上手机打开 Xcode,cmd+shift+2 呼出 Device 的 Window,如图1所示,然后点击 View Device Logs,然后选中对应时间段自己 app 的崩溃日志。如果此时对应的调用栈还没有符号化,可以选中日志后右键如图2所示 Re-Symbolicate Log 即可。

    2、如果是打包服务器或者 Appstore 的包发生闪退:拷贝对应的包和 dSYM 到任意文件夹下,注意将 dSYM 解压以及 .ipa 里面的 .app 取出。然后按照情况1的方式处理即可,Xcode 会自动索引二进制及 dSYM。

    • 如果APP是自己电脑编译生成的,Xcode会根据spotlight自动找到对应的符号文件
    • 如果不是自己电脑编译生成的,只需要将.app和dSYM放入同一文件夹,然后手动生成索引,这样Xcode也能找到。在命令行中输入如下命令手动创建索引:
    # mdimport ,导入文件到datastore(import file hierarchies into the metadata datastore)。
    mdimport pathName
    
    

    上面两种方式确保了Xcode能依据UUID找到地址对应的符号文件,这样,Xcode就能解析出崩溃日志。

    3、如果拿到别的设备导出的未符号化的崩溃日志,可以将日志拖至下图所示的列表中,注意此时上面 tab 记得选 All Logs 而不是 This Device,然后参考情况2,找到崩溃日志对应的二进制包和 dSYM 文件,按照情况2处理即可。可能会遇到系统库的一些方法无法符号化的问题,只需要找到对应的设备连上电脑,让 Xcode 读取一遍该设备(同机型和系统版本的也可以)的符号表,然后再 Re-Symbolicate 一遍就行。

    image

    4、遇到线上用户崩溃,无法拿到完整崩溃日志,可以让用户到【设置->分析->分析数据】里面找到对应时间点的崩溃日志,然后截图,根据一个开源工具 dSYMTools,把崩溃栈的关键地址输入到文本框中即可解析出崩溃的那个方法,具体使用方法参考 answer-huang/dSYMTools: dSYM analyze

    作为一个开发者,有一个学习的氛围和一个交流圈子特别重要,这是我的交流群,点击进群(123),大家有兴趣可以进群里一起交流学习!

    收录:原文地址

    相关文章

      网友评论

          本文标题:iOS Crash 流程化1:一般的 Crash 日志解析方法

          本文链接:https://www.haomeiwen.com/subject/ljgpbctx.html