作者 | 守望 责编 | 郭芮 Linux常用命令中有一些命令可以在开发或调试过程中起到很好的帮助作用,有些可以帮助了解或优化我们的程序,有些可以帮我们定位疑难问题。 本文将简单介绍一下这些命令。 示例程序 我们用一个小程序,来帮助后面我们对这些命令的描述,程序清单cmdTest.c如下: #include<stdio.h> 编译获得elf文件cmdTest并运行: gcc -g -o cmdTest cmdTest.c 程序内容是在main函数中调用test,计算a/b的值,其中b的值为0,因此程序由于除0错误异常终止。 查看文件基本信息——file file cmdTest 通过file命令可以看到cmdTest的类型为elf,是64位、运行于x86-64的程序,not striped表明elf文件中还保留着符号信息以及调试信息等不影响程序运行的内容。 查看程序依赖库——ldd ldd cmdTest 我们可以看到cmdTest依赖了libc.so等库。 查看函数或者全局变量是否存在于elf文件中——nm nm命令用于查看elf文件的符号信息。文件编译出来之后,我们可能不知道新增加的函数或者全局变量是否已经成功编译进去。这时候,我们可以使用nm命令来查看。 例如,查看前面所提到的elf文件有没有test函数,可以用命令: nm cmdTest|grep test 按照地址顺序列出符号信息: nm -n cmdTest 可以看到test函数的开始地址为0x000000000040052d,结束地址为0x0000000000400540。 打印elf文件中的可打印字符串——strings 例如你在代码中存储了一个版本号信息,那么即使编译成elf文件后,仍然可以通过strings搜索其中的字符串甚至可以搜索某个.c文件是否编译在其中: strings elfFile| grep "someString" 查看文件段大小——size 可以通过size命令查看各段大小: size cmdTest
当我们知道各个段的大小之后,如果有减小程序大小的需求,就可以有针对性的对elf文件进行优化处理。 为elf文件”瘦身“——strip strip用于去掉elf文件中所有的符号信息: ls -al cmdTest 可以看到,“瘦身”之后,大小减少将近三分之一。 但是要特别注意的是,“瘦身”之后的elf文件由于没有了符号信息,许多调试命令将无法正常使用,出现core dump时,问题也较难定位,因此只建议在正式发布时对其进行“瘦身”。 查看elf文件信息——readelf readelf用于查看elf文件信息,它可以查看各段信息,符号信息等,下面的例子是查看elf文件头信息: readelf -h cmdTest 从elf头信息中,我们可以知道该elf是64位可执行文件,运行在x86-64中,且字节序为小端序。另外,我们还注意到它的入口地址是0x400440(_start),而不是400540(main)。也就是说,我们的程序运行并非从main开始。 反汇编指定函数——objdump objdump用于展示elf文件信息,功能较多,在此不逐一介绍。有时候我们需要反汇编来定位一些问题,可以使用命令: objdump -d cmdTest #反汇编整个cmdTest程序 但是如果程序较大,那么反汇编时间将会变长,而且反汇编文件也会很大。如果我们已经知道了问题在某个函数,只想反汇编某一个函数,怎么处理呢? 我们可以利用前面介绍的nm命令获取到函数test的地址,然后使用下面的方式反汇编: objdump -d cmdTest --start-address=0x40052d --stop-address=0x400540 ##反汇编指定地址区间 端口占用情况查看——netstat 我们可能常常会遇到进程第一次启动后,再次启动会出现端口绑定失败的问题,我们可以通过netstat命令查看端口占用情况: netstat -anp|grep 端口号 core dump文件生成配置——ulimit -c 有时候我们的程序core dump了却没有生成core文件,很可能是我们设置的问题: ulimit -c #查看core文件配置,如果结果为0,程序core dump时将不会生成core文件 调试神器——gdb gdb是一个强大的调试工具,但这里仅介绍两个简单使用示例。 有时候程序可能已经正在运行,但是又不能终止它,这时候仍然可以使用gdb调试正在运行的进程: gdb processFile PID #processFile为进程文件,pid为进程id,可通过ps命令查找到 有时候程序可能core dump了,但是系统还留给了我们一个礼物——core文件。 在core文件生成配置完成之后,运行cmdTest程序,产生core文件。我们可以用下面的方法通过core文件定位出错位置: gdb cmdTest core #processFile为进程文件,core为生成的core文件 输入bt后,就可以看到调用栈了,出错位置在test函数,cmdTest.c的第4行。 定位crash问题——addr2line 有时候程序崩溃了但不幸没有生成core文件,是不是就完全没有办法了呢?还是cmdTest的例子。运行完cmdTest之后,我们通过dmesg命令可以获取到以下内容: [27153070.538380] traps: cmdTest[2836] trap divide error ip:40053b sp:7ffc230d9280 error:0 in cmdTest[400000+1000] 该信息记录了cmdTest运行出错的基本原因(divide error)和出错位置(40053b),我们使用addr2line命令获取出错具体行号: addr2line -e cmdTest 40053b 可以看到addr2line命令将地址(40053b)翻译成了文件名(cmdTest.c)和行号(4),确定了出错位置。 总结 本文对以上命令仅介绍其经典使用,这些命令都还有其他一些有帮助的用法,但由于篇幅有限,不在此介绍,更多使用方法可以通过man命令名的方式去了解。
热 文 推 荐 ☞ OPPO 推出 10 亿引力计划,全力构建智能化服务生态 ☞ 开除“野狗”式程序员,团队的效率提高了 ☞ 16 岁程序媛遭辍学歧视死亡威胁,最终是如何开发出爆款应用的? ☞ 雷军:执掌金山纯属意外 ☞ 关于5G接入网,看这一篇就够啦! ☞ 别说创业维艰,16岁开发者从辍学歧视死亡威胁, 到开发出爆款应用, 她的人生远非成人想象 ☞ AI in 美团:吃喝玩乐背后的黑科技 ☞ 老程序员肺腑忠告:千万别一辈子靠技术生存! print_r('点个好看吧!'); var_dump('点个好看吧!'); NSLog(@"点个好看吧!"); System.out.println("点个好看吧!"); console.log("点个好看吧!"); print("点个好看吧!"); printf("点个好看吧!\n"); cout << "点个好看吧!" << endl; Console.WriteLine("点个好看吧!"); fmt.Println("点个好看吧!"); Response.Write("点个好看吧!"); alert("点个好看吧!") echo "点个好看吧!" 点击“阅读原文”,打开 CSDN App 阅读更贴心! 喜欢就点击“好看”吧! ---------------------------------------------------------------------------------------------------------------------- 我们尊重原创,也注重分享,文章来源于微信公众号:CSDN,建议关注公众号查看原文。如若侵权请联系qter@qter.org。 ---------------------------------------------------------------------------------------------------------------------- |