CentOS 7 中如何启用coredump,一个shell脚本搞定
引言
为了尽可能的提高服务的可用性,在程序部署时,我们通常会打开很多的辅助功能:
- 监控报警类:帮助我们迅速发现问题快速恢复服务。如端口监控、健康检查等
- 日志类:通常在线上我们会禁用应用程序TRACE、DEBUG等级别的日志,启用INFO等级以上的日志,便于留痕和事后追溯。另外一个方面,我们会启用linux的coredump功能,一旦程序崩溃,让其把程序的堆栈、内存等信息进行转储,方便我们事后确定问题原因。
- 守护类:如monit等进程监测程序,当进程崩溃后,可以重新拉起进程,避免我们手动重启时间太长,影响用户。在实际的互联网产品服务中,当用户发现问题,到运营反馈给产品,产品再反馈给技术排查,技术找到原因让运维重启等这一串流程下来,可能已经过去1个小时了,这个时候写故障报告就不可避免。
在这里,主要介绍一下coredump如何启用,网上的教程也很多,除此之外,再介绍一下可能会遇到的坑。
启用coredump转储
PS:本文的方法适用于CentOS6.6 - CentOS 7.2
如果按照下列步骤操作无效,请先手动编辑/etc/security/limits.conf(需手动删除文件内部分内容,见coredump.sh)、/etc/sysctl.conf(可直接删除)
创建coredump.sh
注意,下面的shell脚本执行后,会把coredump文件存储在/data/imcorefile路径下面。
$ vim coredump.sh
#!/bin/bash
# Filename: coredumpshell.sh
# Description: enable coredump and format the name of core file on centos system
# enable coredump whith unlimited file-size for all users
echo -e "\n# enable coredump whith unlimited file-size for all users\n* soft core unlimited" >> /etc/security/limits.conf
# 存储路径,改了这里别忘记同时修改下面的/data/imcorefile
cd /data && mkdir imcorefile && chmod 777 imcorefile
# format the name of core file.
# %% – 符号%
# %p – 进程号
# %u – 进程用户id
# %g – 进程用户组id
# %s – 生成core文件时收到的信号
# %t – 生成core文件的时间戳(seconds since 0:00h, 1 Jan 1970)
# %h – 主机名
# %e – 程序文件名
# for centos7 system(update 2017.4.2 21:44)
# /data/imcorefile/:是core文件存储的路径,这里比较重要
echo -e "\nkernel.core_pattern=/data/imcorefile/core-%e-%s-%u-%g-%p-%t" >> /etc/sysctl.conf
echo -e "\nkernel.core_uses_pid = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
永久启用core dump功能
$ chmod 777 coredump.sh
$ ./coredump.sh
# 重新打开终端
$ ulimit -a # 显示 unlimited 代表成功
core file size (blocks, -c) unlimited # 生成core转储文件的大小,这里是不限制
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 15085
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65536 # 最大可打开文件句柄数,约等于tcp最大连接数
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 131072
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
验证
$ vim test.c // 输入如下内容
#include <stdio.h>
int main( int argc, char * argv[] ) { char a[1]; scanf( "%s", a ); return 0; }
$ gcc test.c -o test # 编译
$ ./test # 执行test,然后任意输入一串字符后按回车,如zhaogang.com
$ ls /data/imcorefile # 在此目录下如果生成了相应的core文件core-test-*,代表成功
关闭
core文件比较大,有些时候希望关闭这个功能,节省存储空间
$ ulimit -c # 查看core dump状态,0代表关闭,unlimited代表打开
$ vim /etc/profile # 加入如下一句话
# No core files by default
ulimit -S -c 0 > /dev/null 2>&1
# 重新打开终端
$ ulimit -c # 如果输出0,代表关闭成功,如果要重新启用,把上面那句话注释,重新打开终端即可
实战踩坑记录
GDB看不到具体源代码或者显示问号
- 可能是少了-g指令,在CMakeLists.txt增加一下:
# -g:添加gdb调试选项。
ADD_DEFINITIONS(-g -W -Wall -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DAC_HAS_INFO
-DAC_HAS_WARNING -DAC_HAS_ERROR -DAC_HAS_CRITICAL -DTIXML_USE_STL
-DAC_HAS_DEBUG -DLINUX_DAEMON -std=c++11)
- 数组越界了也会导致这种问题
$ vim test.c
#include <stdio.h>
int main( int argc, char * argv[] ) { char a[1]; scanf( "%s", a ); return 0; }
$ gcc -g test.c -o test
$ ./test
Segmentation fault (core dumped)
$ gdb test imcorefile/core-test-11-0-0-4240-1621495946
#0 0x0000000000400066 in ?? ()
#1 0x00007ffef9a48198 in ?? ()
#2 0x0000000100000000 in ?? ()
#3 0x0000000000000000 in ?? ()
GDB看到的堆栈很少,感觉错误位置莫名其妙
解决方法:把程序和core文件拷贝到编译机器,使用gdb调试。
额外说一下,现在很多互联网公司都有自己的CI/CD(持续集成)平台,可以实现一键代码部署和机器分发。其本质上是通过脚本来编译程序,然后使用jenkins来进行程序的分发和部署。假设有几套环境:编译机器 -> DEV(开发) -> TEST(测试) -> PRE(预发) -> PROD(生产),这中间我们的任何代码的改动都需要经过这一串的完整流程。故在生产环境运行的程序都不是本机编译的。
所以,这个问题需要注意一下,调试core文件的时候,需要在编译机器上,否则堆栈信息可能误导你!
参考
- CentOS开启coredump转储并生成core文件的配置