首页 > 其他 > 详细

systemd 下的core dump(内核转储)

时间:2014-03-03 05:27:02      阅读:2243      评论:0      收藏:0      [点我收藏+]

如果你使用systemd,那么默认情况下即使开启了转储,当程序确实core dump 的时候,你并不会在当前(包括chdir)目录下找到core(转储)文件。下面非常简短地说下如何在systemd 下得到core 文件。


1. 首先,确定你开启了core dump(内核转储)

ulimit -c
看下值是多少,如果是非0,则代表转储功能开启,如果是0,那么请手动开启:

ulimit -c unlimited
如果不喜欢无限制的转储,那么请在后面指定大小而非"unlimited",例如要指定转储文件最大64MiB:

ulimit -c 67108864
注意:这些设置只在当前的终端下生效,其后会讲到如何在系统中全局设置转储功能。


2. 获得core dump 文件——通过systemd

在systemd 下,有两种方法来获得转储文件,下面先写一段非常简单的导致转储的代码,不妨写地址NULL 罢:

/*
 * filename: dump.c
 * 作用:造成内核转储
 */
#include <stdio.h>

int
main (int argc, char *argv[])
{
  int *p = NULL;
  *p = 0;
  return 0;
}
然后编译-链接-执行,如果不出意料,你应该看到了类似如下信息:

[1]    29041 segmentation fault (core dumped)  a.out

但是如果你(systemd 用户)默认ls 查看的话,是找不到转储文件的。

请执行:

systemd-coredumpctl
或者

systemd-coredumpctl list ‘要匹配的字符串‘
来查看所有的转储记录。

例如core dump 的是smplayer,那么执行:

systemd-coredumpctl list ‘smplayer‘ | tail -n 5
来得到匹配‘smplayer‘ 字符串的最近5 次的转储记录,看准时间记下PID:

systemd-coredumpctl -o core dump PID
获得转储信息,输出到文件core 中。成功的话一般会看到类似下面的信息:

TIME                                         PID   UID   GID SIG EXE
              六 2014-03-01 19:58:58 UTC  18404  1000  1000  11 /home/ispeller/Code/tmp/a.out
More than one entry matches, ignoring rest.
不放心的话

readelf -h your_core_file | grep -ie type

来看一下是否是转储文件。


3. 获得core dump 文件——不通过systemd 而立刻在指定目录获得

这里只写方法,至于为什么这样做,查看你的/usr/src/linux/Documentation/sysctl/kernel.txt 文件,或者在这里找到一份网络版。

关于/proc/sys/kernel/core_pattern 文件有一段这样写道:

If the first character of the pattern is a ‘|‘, the kernel will treatthe rest of the pattern as a command to run.  The core dump will bewritten to the standard input of that program instead of to a file.

而这个文件的默认值在systemd 下,是一个以‘|‘ 字符(其实就是个管道)开头的字符串,一般类似:

| /usr/lib/systemd/systemd-coredump 参数(至于参数请在txt 文件中搜索‘corename format specifiers‘)

我们期望的是在指定目录(例如当前目录)立刻产生转储文件,那么只需要修改core_pattern 即可:

sudo sysctl -w ‘kernel.core_pattern=%t-%e-%p-%c.core\n‘
上面是设置的在当前目录下产生转储文件(因为没加路径)。core 文件的命名格式可以参照kernel.txt 文件自己设置。

这样当你执行一个会导致内核转储的程序的时候,在你指定的目录会得到你期望的东西。


4.试用内核转储掩码来排除要转储的内存块

你可能会因为不希望设置ulimit 的时候太僵硬导致空间不够没有得到完整的转储,所以设置ulimit 为"unlimited" (不限制)。但是如果执行一个占用内存很恐怖的程序,当这个程序内核转储的时候也就会生成体积很恐怖的转储文件。

为了避免这种情况,可以指定内核转储掩码来排除要转储的内存段。

掩码请查看/usr/src/linux/Documentation/sysctl/kernel.txt 中的3.4 小节,没有内核源码可以到这里的网络版,这里摘录出来如下:

The following 7 memory types are supported:
  - (bit 0) anonymous private memory(匿名私有内存段)
  - (bit 1) anonymous shared memory(匿名共享内存段)
  - (bit 2) file-backed private memory(file-backed 私有内存段)
  - (bit 3) file-backed shared memory(file-bakced 共享内存段)
  - (bit 4) ELF header pages in file-backed private memory areas (it is
            effective only if the bit 2 is cleared)(ELF 文件映射,只有在bit 2 复位的时候才起作用)
  - (bit 5) hugetlb private memory(大页面私有内存)
  - (bit 6) hugetlb shared memory(大页面共享内存)

设置方法很简单:找到程序的PID,然后修改/proc/PID/coredump_filter 的值。

如果你要设置某些还没有运行的进程的内核转储掩码,请修改/proc/self/coredump_filter 的值。

PS:默认的coredump_filter 的值一般是0x23,至于代表什么,请换成二进制00100011,从右向左看,bit 0、bit 1、bit 5 被置位,也就是说会转储所有的匿名内存段和大页面私有内存段。


5. 在系统中全局设置转储功能

全局设置没有什么好说的,把你的配置写入/etc/profile.d/ 目录下任意一个新建的文件当中,别忘了设置属组和所有者为root:root,权限为751。

根据上面说的,写入的要有一条ulimit 指令,可能还有一条sysctl 指令,最后可能还有一条cat 指令。

更多的设置请查看kernel.txt 和proc.txt,例如你想把SUID 程序也转储,你需要

sysctl -w ‘fs.suid_dumpable=1‘


写这篇文章主要是因为需要这方面资料的时候,百度上竟然没有发现systemd 下core dump 信息!!…………

甚至你现在百度"systemd core dump"或者"systemd 内核转储" 就可以找到这篇文章了 Orz……

就这样,systemd 下的转储简单介绍完了,祝你愉快~

systemd 下的core dump(内核转储),布布扣,bubuko.com

systemd 下的core dump(内核转储)

原文:http://blog.csdn.net/ispeller/article/details/20232089

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!