Linux 程序异常退出如何分析?

阅读本文,可以收获排查Linux程序异常退出问题的方法,了解异常日志在linux中存储的位置,程序异常挂掉问题的排查思路。

首先要知道,linux系统的配置常常在/etc目录下,比如/etc/profile(记住这个文件会经常用到),而/var则是存储各种变化的文件。比如说log文件:

 /var/log/messages:常规日志消息

 /var/log/boot:系统启动日志

 /var/log/debug:调试日志消息

 /var/log/auth.log:用户登录和身份验证日志

 /var/log/daemon.log:运行squid,ntpd等其他日志消息到这个文件 

 /var/log/dmesg:Linux内核环缓存日志

 /var/log/dpkg.log:所有二进制包日志都包括程序包安装和其他信息

 /var/log/faillog:用户登录日志文件失败

 /var/log/kern.log:内核日志文件

 /var/log/lpr.log:打印机日志文件

 /var/log/mail.*:所有邮件服务器消息日志文件

 /var/log/mysql.*:MySQL服务器日志文件

 /var/log/user.log:所有用户级日志

 /var/log/xorg.0.log:X.org日志文件

 /var/log/apache2/*:Apache Web服务器日志文件目录

 /var/log/lighttpd/*:Lighttpd Web服务器日志文件目录

 /var/log/fsck/*:fsck命令日志

 /var/log/apport.log:应用程序崩溃报告/日志文件

 /var/log/syslog:系统日志

 /var/log/ufw:ufw防火墙日志

 /var/log/gufw:gufw防火墙日志

而程序崩溃一般都会将日志存储在/var/log/apport.log

#1 查看崩溃日志

cd var/log/

vim apport.log

输出

ERROR: apport (pid 23397) Thu Jul  8 13:01:58 2021: called for pid 28198, signal 11, core limit 0, dump mode 1
ERROR: apport (pid 23397) Thu Jul  8 13:01:58 2021: executable: home/racobit/jiafeng/TCP_Agent/proxy (command line "./proxy")
ERROR: apport (pid 23397) Thu Jul  8 13:01:58 2021: executable does not belong to a package, ignoring

上面给我们提供了详细的报错信息:pid 28198, signal 11, core limit 0, dump mode 1

#kill -l 可以列出所有的信号

kill -l

输出:

 1) SIGHUP   2) SIGINT   3) SIGQUIT   4) SIGILL   5) SIGTRAP

 6) SIGABRT   7) SIGBUS   8) SIGFPE   9) SIGKILL  10) SIGUSR1

11) SIGSEGV  12) SIGUSR2  13) SIGPIPE  14) SIGALRM  15) SIGTERM

16) SIGSTKFLT  

...

 61) SIGRTMAX-3  62) SIGRTMAX-2 63) SIGRTMAX-1  64) SIGRTMAX  

上面显示signal 11 是SIGSEGV,意思是程序进行了一次无效的存储访问。

一般数组越界或是访问空指针,都会产生这个信号

core limit 0, dump mode 1我没有查到是什么意思,我猜应该是core dump未开启之类的。

#2 查看内存使用情况

看下程序运行中是否有明显内存溢出的情况。

#-m 以MB为单位显示内存使用信息

free -m

#使用watch 命令动态观测free

#-n 3 代表3s执行一次  -d 则是用高亮显示变化区域

watch -n 3 -d free

发现程序没有明显内存溢出,内存没有一直增长。那么只能分析Core文件了。

在分析前先了解下Core Dump:程序运行过程中异常或者bug导致退出,在满足一定条件下产生一个core文件,这种行为就叫Core Dump (核心转储) 。

在linux下当应用程序发生异常中止退出或者发生崩溃的时候,linux内核会将应用程序在这段运行期间的内存状态等相关信息转存到磁盘,以供系统故障排查或者调试。这个转存的文件叫core dump文件。

core dump文件中会记录程序当时的内存调用、堆栈引用、进程和线程调用等信息,可以帮助开发人员和维护人员了解异常发生当时的环境参数和信息,所以core dump对故障排查和bug调试具有重大的意义。

#3 查看/开启Core Dump

ulimit -a

#可以查看 core file size 大小,为0则说明没有开启

输出:

core file size          (blocks, -c) unlimited

data seg size           (kbytes, -d) unlimited

...



ulimit -c            #查看是否支持coredump 如果为0 需要打开

ulimit -c [kbytes]   #具体命令

ulimit -c 0          #不生产core文件

ulimit -c 100        #设置core文件最大为100k

ulimit -c unlimited  #不限制core文件大小

上面这种方式只能在当前shell中生效,可在/etc/profile配置一直生效(👆有提到哦!)

 #进入配置

vim /etc/profile 

#文件末尾添加    

ulimit -c unlimited  

#保存退出 并source一下

source /etc/profile

配置完成后,当程序异常挂掉,可在程序存放的目录看到core文件

 #4 使用gdb分析生成的core文件。

#5 提炼出关键信息

Program terminated with signal SIGSEGV, Segmentation fault.

# 上面一句给出程序终止给出的信号是SIGSEGV,前面提到过

# SIGSEGV意味着程序进行了一次无效的存储访问



_IO_vfprintf_internal (s=0x0, format=0x5590e62ff8 "[%d/%d/%d %s %d:%d:%d]  ", ap=...)

1283  vfprintf.c: No such file or directory.

# 这句才是重点,首先是说明了IO流,接着说没有文件或者目录。

# 我们又可以看到函数传递参数是,s=0x0,很有可能就个参数,

# int vfprintf(FILE *stream, const char *format, va_list arg)

# 可以确定应该是fPrintf()函数的原因



0x0000007fac69097c in __fprintf (stream=<optimized out>, format=<optimized out>) at fprintf.c:32


#2  0x0000005590e5f9a4 in thread_worker2 ()

#再根据这句,我们可以确定是thread_worker2()中的fprintf函数运行中出错,

#首先我们应该想到,是fopen()中返回的FILE指针出了问题。

#6 程序问题定位并解决

#最后发现程序可能在打开的状态下没colse文件并清除fp2指针。

#这便是句柄泄漏,也说明了为什么一开始能正常,后面就变得不正常。

fp2 = fopen(name, "a")

if (send(sockfd,thread2_buffer,(ctx->thread2_send_len),0) <= 0 )

{

 break;

}

fprintf(fp2, "%d\r\n", 11);

fclose(fp2);

fp2 = NULL;



#解决办法,在send失败后,break循环之前,先进行colse文件,清除指针。

if (send(sockfd,thread2_buffer,(ctx->thread2_send_len),0) <= 0 )

{

  fclose(fp2);

  fp2 = NULL;

  break;

}

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值