我有一个设置,其中多台机器通过 NFS 共享相同的文件系统。通过排队系统,处理作业可以提交给多个计算机(具有不同的属性)。
有时,作业会崩溃并留下核心文件(名称类似于core.1234
)。
有没有办法找出哪个主机生成了该核心文件?它的主机名是什么?
(这是在 Linux 64 位上,如果有区别的话)。
答案1
在一个极低频系统中,核心文件几乎肯定是有效的 ELF 文件。
$ readelf -a core
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: CORE (Core file)
Machine: Intel 80386
[...]
平台特定数量的“注释”被添加到注释段中,以便调试器可以找到它的方法,例如对于 Solaris,请参阅核心(4),您将注意到NT_UTSNAME
包含系统调用中的数据结构的结构uname(2)
。elfdump -n
是这样的阅读方式,但据我所知,Solaris 是唯一执行此操作的操作系统(我怀疑只有 Solaris 11elfdump
可以按预期工作)。
一种简单但稍显繁琐且无法保证的方法是尝试从核心转储环境中获取HOST
或HOSTNAME
变量(由某些启动脚本和 shell 设置,bash
至少是 set )。HOSTNAME
您可以使用 来执行此操作gdb
,但您需要原始二进制文件:
$ gdb /usr/bin/sleep core
[... snip ...]
(gdb) print (char ***) &environ
$1 = (char ***) 0x600bf8
(gdb) print $1[0][0]@10
$2 = {0x7fffffffd9c9 "HOST=myhostname", 0x7fffffffd9d9 "TERM=screen",
0x7fffffffd9e5 "SHELL=/bin/csh",
[...]
这environ
从符号中打印一大块字符串。虽然这是一个可怕的黑客,strings | grep HOSTNAME=
但也可能有效。
所以,简短回答“有没有办法找出哪个主机生成了该核心文件“在 Linux 上并不容易,而且也不可靠。
FWIW,Linux 上的相关 coredump 代码位于fs/binfmt_elf.c
,并且有一个钩子可以通过以下方式允许额外的“注释”ARCH_HAVE_EXTRA_ELF_NOTES
,目前仅在 PowerPC 上使用。)
更好的计划是使用sysctl设置核心文件名在每个客户端上,按照 @jlliagre 的建议:
sysctl kernel.core_pattern="%h-%t-%e.core"
(这里sysctl
的 ferreting around/proc
是等价的,我更喜欢,sysctl
因为可以将更改记录下来,/etc/sysctl.conf
并且它也可以在 *BSD 系统上使用。)
答案2
您可以运行strings core.1234
并查看主机名是否出现在某处。某些操作系统(例如 Solaris)确实将主机名放在核心标头中,但据我所知,Linux 没有这样做,因此该strings
方法对此不可靠。
更好的方法是通过设置文件或某些特定于发行版的配置(如果引用可执行文件)来配置NFS
客户端,将其主机名放入核心文件名中。/proc/sys/kernel/core_pattern
core_pattern