coredump
linux原生
一、设置
$ cat /proc/sys/kernel/core_pattern
通过查看core_pattern文件,发现其确实指定了一个路径,于是我前往那个路径,发现竟然是脚本程序,后来查看说明文件,才知道core_pattern中如果首先指定了一个 ‘|’ 管道符,则会将生成的core文件传递给后面所跟的脚本去处理。
至此,也就确定了问题的原因,| 管道符后面的脚本将我们的core文件给吞了,解决方法自然就是去掉这个脚本,换成自己指定的目录,要保证存放Coredump的目录存在且进程对该目 录有写权限
若程序调用了seteuid()/setegid()改变 了进程的有效用户或组,则在默认情况下系统不会为这些进程生成Coredump。很多服务程序都会调用seteuid(),如MySQL,不论你用什么用 户运行mysqld_safe启动MySQL,mysqld进行的有效用户始终是msyql用户。如果你当初是以用户A运行了某个程序,但在ps里看到的 这个程序的用户却是B的话,那么这些进程就是调用了seteuid了。为了能够让这些进程生成core dump,需要将/proc/sys/fs
要设置足够大的Core文件大小限制 。程序崩溃时生成的Core文件大小即为程序运行时占用的内存大小。但程序崩溃时的行为不可按平常时的行为来估计,比如缓冲区溢出等错误可能导致堆栈被 破坏,因此经常会出现某个变量的值被修改成乱七八糟的,然后程序用这个大小去申请内存就可能导致程序比平常时多占用很多内存。因此无论程序正常运行时占用 的内存多么少,要保证生成Core文件还是将大小限制设为unlimited为好。
二、修改core位置
直接去修改core_pattern文件并没有成功,保存时会提示FSync错误,查阅资料得知,这个文件有特殊限制,只能通过命令:
sudo bash -c "echo 这里是写入内容 > /proc/sys/kernel/core_pattern "
我使用:
sudo bash -c "echo core > /proc/sys/kernel/core_pattern "
来进行写入,即指定程序所在目录为core文件生成目录,core文件名称为"core"。
可以通过修改kernel的参数来指定内核生成的coredump文件的文件名。常见设置如下:
方式一:
echo "/data/coredump/core.%e.%p" > /proc/sys/kernel/core_pattern
echo "|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h" > /proc/sys/kernel/core_pattern
方式二:
vim /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
/data/coredump是你自己指定的存放coredump文件的路径,所有产生的coredump文件将会存放在这里,%e表示程序的文件名,%p表示进程的ID(当然还有一些其他的参数可以设置,例:%t显示创建的时间),但是前提要把目录/data/coredump创建好,不然无法生成文件
永久修改:使用sysctl -w name=value命令,/sbin/sysctl -w kernel.core_pattern=core-%p-%e
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间(由1970年1月1日计起的秒数)
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名(程序文件名)
三、修改core文件大小
linux系统默认生成core文件时空,可以用命令查看
ulimit -c
//详细信息
ulimit -a
如果结果是0,我们需要修改其大小
//当前有效的修改
ulimit -c [size] //这里size一般修改为unlimited,或者是其他数字(kbytes):2048
如果生成的信息超过此大小,将会被裁剪,最终生成一个不完整的core文件。在调试此 core文件的时候,gdb会提示错误。
以上修改只对当前的shell有效,一旦关闭,则恢复原来的值
设置永久有效
打开 /etc/security/limits.conf文件
添加两行:
* soft core unlimited
* hard core unlimited
测试结果
不同设置情况下的core大小
Minicoredumper
编译安装
Git clone https://github.com/diamon/minicoredumper.git
安装autotools系列工具
要安装的工具有autoconf,automake,autopoint,libtool,gettext。
yum install -y autoconf
yum install -y automake
yum install -y libtool
yum install -y gettext
yum install -y autopoint 或者 yum install -y gettext-devel
若上述安装失败则使用以下安装方式为包管理工具(apt,yum)安装不了的情况下使用的。
下载地址: Index of /gnu/
下载tar.gz包
然后解压缩,
执行./configure命令,
执行make && make install 命令
autoreconf --install
./configure
configure: error: gelf.h missing!
yum install elfutils-libelf-devel
configure: error: json-c/json.h missing!
$ git clone https://github.com/json-c/json-c.git
$ mkdir json-c-build
$ cd json-c-build
$ cmake ../json-c #See CMake section below for custom arguments
$ make
$ make test
$ make USE_VALGRIND=0 test#optionally skip using valgrind
$ sudo make install #it could be necessary to execute make install
来自 <https://github.com/json-c/json-c>
make
corestripper.c:32:10: 致命错误:elfutils/version.h:没有那个文件或目录
yum install -y elfutils-devel
make install
使用
修改code路径
$ echo '|/usr/sbin/minicoredumper %P %u %g %s %t %h %e' | tee /proc/sys/kernel/core_pattern
$ echo 0x7fffffff | tee /proc/sys/kernel/core_pipe_limit
修改配置
{
#一组选项,指定如何转储以及转储哪些堆栈
"stacks": {
"dump_stacks": true, #是否应进行堆栈转储。如果此选项为false,则忽略所有其他堆栈选项。
"first_thread_only": false, #是否只应转储崩溃线程的堆栈
"max_stack_size": 0 #要转储的最大堆栈大小(以字节为单位)。0表示无限制。只转储堆栈区域的实际使用部分。如果堆栈由于max_stack_size选项而被截断,则会转储所用堆栈的最底部(即堆栈中包括导致核心转储的函数的部分)
},
#指定共享对象的一组选项,其虚拟内存区域也应转储,如果共享对象维护调试期间所需的静态堆栈外数据,这将非常有用
"maps": {
#要转储的共享对象名称, 名称可以包含用于通配符匹配的*字符
"dump_by_name": [
"*my_lib_to_debug*so*",
"[vdso]"
]
},
#一组缓冲区,每个缓冲区指定应用程序中也应转储的全局数据
"buffers": [
{
"symname": "my_allocated_struct", #全局变量/符号的名称
"follow_ptr": true, #全局变量是否是指针,该指针指向的数据是否应该转储
"data_len": 42 #全局变量的大小(以字节为单位)。如果follow_ptr为true,则这是指向的数据的大小
},
{
"symname": "my_short",
"follow_ptr": false,
"data_len": 2,
"ident": "my_short_data.bin" #以后用于标识二进制转储的可选字符串
}
],
#用于指定文件是否应使用压缩以及应使用何种类型的压缩
"compression": {
"compressor": "gzip",
"extension": "gz",
"in_tar": true
},
"dump_auxv_so_list": true, #是否应转储共享对象列表, 使用它来确定链接了哪些共享对象以及将它们映射到哪个地址
"dump_pthread_list": true, #是否应转储pthread列表,使用它来识别和遍历所有线程
"dump_robust_mutex_list": true, #是否应转储健壮互斥的列表, 使用它来标识共享内存中的互斥对象属性和状态
"dump_scope": 8, #只有达到或低于此值的已注册转储才会被转储
"live_dumper": false, #是否应触发所有已注册的.BR libminicoredumpr(7)应用程序
"write_proc_info": true, #是否应将感兴趣的/proc文件复制到转储目录
"write_debug_log": false, #否应将.BR minicoredumper(1)消息记录到转储目录中的“debug.txt”中。如果.BR syslog(3)在系统上不可用,则此选项特别有用
"dump_fat_core": false #是否应转储所有虚拟内存区域。 这将生成一个单独的“fatcore”文件,该文件通常比默认的Linux.BR core(5)文件大。这实际上只对调试.BR minicoredumper(1)有用。
}
dump_auxv_s_list、 dump_phread_list、 dump_robust_mutex_list 选项通常应设置为true。它们为gdb提供了重要信息,并且需要相对较小的转储空间。