core dump filename gets thread name instead of executable name with core_pattern %e.%p.core

为君一笑 提交于 2019-12-04 05:29:42

The executable name that generated the core can be retrieved by using gdb. The following prints it:

gdb -batch -ex "core corefile" | grep "Core was generated" | cut -d\` -f2 | cut -d"'" -f1 | awk '{print $1}'

Or better yet use the pid %p and /proc to get it. Example:

$ sleep 900 &
[1] 2615
$ readlink /proc/$(pidof sleep)/exe
/bin/sleep
$ basename $(readlink /proc/$(pidof sleep)/exe)
sleep

So I wound up working around the issue by piping the core dump to a Python script which then renames the core filename based on a hard-coded mapping of thread name regex patterns to executable name.

Here's how to pipe the core to a script:

/sbin/sysctl -q -w "kernel.core_pattern=|/opt/mydirectory/bin/core_helper.py --corefile /opt/mydirectory/coredumps/%e.%p.core"
/sbin/sysctl -q -w "kernel.core_pipe_limit=8"

Here's a snippet of a class in core_helper.py. As a bonus, if you give the core filename a .gz extension, it will compress the coredump with gzip.

class CoredumpHelperConfig:
    def __init__(self, corefile):
        self.corefile = corefile

    # Work-around: Linux is putting the thread name into the 
    # core filename instead of the executable. Revert the thread name to 
    # executable name by using this mapping.
    # The order is important -- the first match will be used. 
    threadNameToExecutableMapping = [# pattern       , replace
                                      (r'fooThread.*', r'foo'),
                                      (r'barThread.*', r'foo'),
                                    ]

    def processCore(self):
        (dirname, basename) = os.path.split(self.corefile)
        # E.g. fooThread0.21495.core (no compression) or fooThread0.21495.core.gz (compression requested)
        match = re.match(r'^(\w+)\.(\d+)\.(core(\.gz)?)$', basename)
        assert match
        (threadName, pid, ext, compression) = match.groups()
        # Work-around for thread name problem
        execName = threadName
        for (pattern, replace) in CoredumpHelperConfig.threadNameToExecutableMapping:
            match = re.match(pattern, threadName)
            if match:
                execName = re.sub(pattern, replace, threadName)
                break
        self.corefile = os.path.join(dirname, '.'.join([execName, pid, ext]))
        # Pipe the contents of the core into corefile, optionally compressing it
        core = open(self.corefile, 'w')
        coreProcessApp = "tee"
        if(compression):
            coreProcessApp = "gzip"
        p = subprocess.Popen(coreProcessApp, shell=True, stdin=sys.stdin, stdout=core, stderr=core)
        core.close()
        return True

I'll leave it as an exercise to the reader on how to write the rest of the file.

I have the same problem. And I have worked around with the same way. I get executable filename use /proc/pid/exe

src_file_path = os.readlink("/proc/%s/exe" %pid)
exec_filename = os.path.basename(src_file_path)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!