查找DSYM
在iOS开发中,经常需要针对线上应用异常来定位问题,这个处理大多数情况下会由第三方的异常收集工具来完成,例如Umeng,Bugly等。但是在一些要求比较严格的场景(例如对于应用信息和安全要求比较高的金融类应用中)或者忘记上传DSYM文件的情况下,就需要我们自己来根据异常日志来处理异常.
根据异常日志定位异常要做的第一步就是找到版本对应的DSYM文件.那么该如何查找这个文件呢?
根据UUID确定DSYM文件
首先需要在Xcode中,设置生成DSYM文件,
- 在TARGETS->Build settings中,打开Generate Debug Symbols,选择YES;
- 在TARGETS->Build settings中,打开Debug Infomation FormatM<kbd>中,选择DWARF with DSYM file选项.
设置完成之后在每次打包成功时,都会生成对应的.dSYM文件和.app文件.而每次生成的.dSYM文件和.app都会有一个独立的uuid来唯一标示该次打包过程.可以使用
dwarfdump --uuid xxx.dSYM
// 可以简写为:
dwarfdump -u xxx.dSYM
来查看文件的UUID标识.而且只有同一次打包过程生成的.dSYM文件和.app文件才具有同一个UUID,这样就可以根据.app的文件的UUID来查找对应的.dSYM文件.
找到DSYM文件所在的目录
一般如果没有人为改动的情况下,DSYM文件会存储在~/Library/Developer/Xcode,如果你知道了这个目录,想要查找对应的DSYM文件就会变得很简单:
- 使用find命令来查找当前路径下的所有.dSYM文件
allFiles=`find ~/Library/Developer/Xcode/Archives -iname '*.dSYM'`
当然如果想要更加精确一点可以添加上-type参数:
filesPath=`find ~/Library/Developer/Xcode/Archives -iname '*.dSYM' -type f`
如果你不知道这个路径或者是自自定义了.dSYM文件的存储路径但是记不起来了,也没有关系可以通过
find ~ -iname 'Archives' -type d 2>/dev/null | grep 'Xcode'
来查找文件的目录.
- 将获取到的所有.dSYM文件路径转化为数组:
// 保存之前的IFS分隔符
OLD_IFS=$IFS
IFS=$'\n'
allFiles=$(filesPath)
- 遍历allFiles数组,查看每一个.dSYM文件的UUID:如果当前文件的UUID与所要寻找的UUID一致,则输出;否则,继续下一个文件:
for file in ${allFiles[@]}
do
uuid=`dwarfdum --uuid ${file}`
if [ $uuid =~ '771D2534-945F-3D1C-xxxx-77C881D32FA5' ];then
echo "The path of file to be searched is ${file}"
fi
done
// 恢复分隔符
IFS=$OLD_IFS
这样通过运行脚本,就可以找到与线上app对应的.dSYM文件,然后就可以[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传定位异常位置。
完整代码大概这个样子:
#!/bin/zsh
basePath=~/Library/Developer/Xcode/Archives;
cd ${basePath}
allFiles=`find . -iname '*.dsym'`
OLD_IFS=$IFS
IFS=$'\n'
fliesArray=($allFiles)
for file in ${fliesArray[@]}
do
uuid=`dwarfdump -u ${file}`;
if [[ $uuid =~ '771D2534-945F-3D1C-xxxx-77C881D32FA5' ]]
then
echo "The path of file to be searched is ${file}"
fi
done
IFS=$OLD_IFS
当然如果你觉得这样运行脚本并不是很方便或者已经非常熟悉这个操作可以把上述代码进行简化:
find ~/Library/Developer/Xcode -iname '*.dSYM' -print0 | xargs -0 dwarfdump -u | grep '771D2534-945F-3D1C-xxxx-77C881D32FA5'
同样可以实现查找指定.dSYM文件的目的.在这个命令中,使用了-print0和xargs -0,是因为:
find命令会使用系统默认的分隔符号分割字符串(空格,换行符号以及制表符),但是由于查找的路径中存在空格等符号就会导致一个正常的路径可能会被分割为多个字串,但这并不是想要的结果。这时候就可以使用-print0 和xargs -0一起使用,其综合作用的结果就是find使用了一个不可见的NULL字符来分割查找到的结果,然后通过管道符将参数传递给xargs,而管道符取参数时也按照NULL为分隔符去取元素传递给下一个命令。之所以可以这么操作是因为多数编程语言都会选择将NULL作为字符串结束的标志,所以正常的字符串中不会包含NULL字符