【问题标题】:core dump files on Linux: how to get info on opened files?Linux 上的核心转储文件:如何获取打开文件的信息?
【发布时间】:2010-09-08 16:24:44
【问题描述】:

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

【问题讨论】:

    标签: linux crash coredump


    【解决方案1】:

    如果你有一个核心文件并且你已经使用调试选项(-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)。

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

    【讨论】:

    • 这并没有真正回答问题,即使用核心文件来发现打开的文件,而不是向现有程序添加调试输出。 Oliver 无论如何都无法重现该问题。
    【解决方案2】:

    最好的办法是为使程序崩溃的任何信号(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
    

    然后你可以从你的信号处理程序返回,你应该像往常一样得到一个核心转储。

    【讨论】:

      【解决方案3】:

      我跳转到此信息的一种方法是在核心文件上运行strings。例如,当我最近在核心上运行文件时,由于文件夹的长度,我会得到一个截断的参数列表。我知道我的运行会从我的主目录打开文件,所以我只是运行:

      strings core.14930|grep jodie
      

      但这是一个我有一根针和一个干草堆的案例。

      【讨论】:

        【解决方案4】:

        您可以尝试使用strace 来查看程序发出的opensocketclose 调用。

        编辑:我认为您无法从核心获取信息;最多它会在某个地方有文件描述符,但这仍然没有给你实际的文件/套接字。 (假设您可以区分打开和关闭的文件描述符,我也对此表示怀疑。)

        【讨论】:

          【解决方案5】:

          如果程序忘记关闭这些资源,可能是因为发生了以下情况:

          fd = open("/tmp/foo",O_CREAT);
          //do stuff
          fd = open("/tmp/bar",O_CREAT); //Oops, forgot to close(fd)
          

          现在我不会在内存中拥有 foo 的文件描述符了。

          如果这没有发生,您也许可以找到文件描述符编号,但话又说回来,这不是很有用,因为它们在不断变化,当您开始调试时,您将不知道是哪个文件它实际上是当时的意思。

          我真的认为您应该使用 strace、lsof 和朋友进行现场调试。

          如果有办法从核心转储中做到这一点,我也很想知道:-)

          【讨论】:

            【解决方案6】:

            最近在我的错误排除和分析过程中,我的客户向我提供了一个在他的文件系统中生成的 coredump,他离开站以便快速扫描文件并读取其内容,我使用了该命令

            字符串 core.67545 > coredump.txt 后来我能够在文件编辑器中打开文件。

            【讨论】:

              【解决方案7】:

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

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

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

              【讨论】:

                【解决方案8】:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多