Linux下的核心转储文件:如何获取已打开文件的信息?

34

我有一个核心转储文件,其中的进程可能存在文件描述符泄漏(它打开了一些文件和套接字,但显然有时忘记关闭其中一些)。有没有办法找出进程在崩溃前打开了哪些文件和套接字?由于难以重现崩溃,因此分析核心文件似乎是获取有关错误提示的唯一方法。

8个回答

10
如果您有一个核心文件,并且使用调试选项(-g)编译了程序,则可以看到核心转储的位置:
$ gcc -g -o something something.c
$ ./something
Segmentation fault (core dumped)
$ gdb something core

您可以使用这个方法进行后期调试。以下是一些gdb命令:bt打印堆栈,fr跳转到指定的堆栈帧(参见bt输出)。

现在,如果您想查看在段错误时打开了哪些文件,只需处理SIGSEGV信号,在处理程序中,只需倾倒/proc/PID/fd目录的内容(例如使用system('ls -l /proc/PID/fs')或execv)。

有了这些信息,您就可以轻松找出导致崩溃的原因,打开了哪些文件以及崩溃和文件描述符泄漏是否有关联。


4
这并没有回答问题,问题是关于使用核心文件来发现打开的文件,而不是在现有程序中添加调试输出。Oliver 无法复现此问题。 - craig65535

6
你最好为导致程序崩溃的信号(SIGSEGV等)安装一个信号处理程序。在信号处理程序中,检查/proc/self/fd,并将内容保存到文件中。以下是可能会看到的示例:
Anderson cxc # ls -l  /proc/8247/fd
total 0
lrwx------ 1 root root 64 Sep 12 06:05 0 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 12 06:05 1 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 12 06:05 10 -> anon_inode:[eventpoll]
lrwx------ 1 root root 64 Sep 12 06:05 11 -> socket:[124061]
lrwx------ 1 root root 64 Sep 12 06:05 12 -> socket:[124063]
lrwx------ 1 root root 64 Sep 12 06:05 13 -> socket:[124064]
lrwx------ 1 root root 64 Sep 12 06:05 14 -> /dev/driver0
lr-x------ 1 root root 64 Sep 12 06:05 16 -> /temp/app/whatever.tar.gz
lr-x------ 1 root root 64 Sep 12 06:05 17 -> /dev/urandom

然后你可以从你的信号处理程序中返回,通常情况下应该会获得一个核心转储。


4

在 IT 技术中,有一种方法可以快速获取信息,就是对核心文件运行 strings 命令。例如,最近我运行 file 命令来分析一个核心文件,但由于文件夹名字过长,参数列表被截断了。我知道我的运行会打开来自我的主目录的文件,因此我只需输入以下命令:

strings core.14930|grep jodie

但这是我手头只有针和一堆干草的情况。

2

最近在进行错误排除和分析时,我的客户向我提供了一个核心转储文件,该文件在他的文件系统中生成,他离开了工作地点,为了快速扫描文件并阅读其内容,我使用了以下命令:

strings core.67545 > coredump.txt 稍后,我能够在文件编辑器中打开该文件。


2
您可以尝试使用strace来查看程序所做的opensocketclose调用。编辑:我认为您无法从核心中获取信息;最多它会在某个地方有文件描述符,但这仍然不能给您实际的文件/套接字。(假设您可以区分打开和关闭的文件描述符,我也怀疑。)

2
如果程序忘记关闭这些资源,可能是因为发生了以下类似的情况:
fd = open("/tmp/foo",O_CREAT);
//do stuff
fd = open("/tmp/bar",O_CREAT); //Oops, forgot to close(fd)

现在我不会在内存中保留foo的文件描述符。

如果没有这种情况发生,你可能能够找到文件描述符号码,但是这并不是很有用,因为它们不断变化,在调试时你将不知道它实际上表示的是哪个文件。

我认为你应该使用strace、lsof等工具进行在线调试。

如果有一种方法可以从核心转储中完成它,我也很想知道它:-)


1

核心转储是进程崩溃时访问的内存的副本。根据泄漏发生的方式,它可能已经丢失了对句柄的引用,因此可能被证明是无用的。

lsof列出系统中当前打开的所有文件,您可以检查其输出以查找泄漏的套接字或文件。是的,您需要让进程运行。您可以使用特定的用户名运行它,以轻松区分正在调试的进程的打开文件。

我希望有人拥有更好的信息 :-)


0

另一种在运行时找出进程打开了哪些文件的方法是查看 /proc/PID/fd/,其中包含指向打开文件的符号链接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接