如何查找 bash 退出并显示信号 11 的原因,分段错误

如何查找 bash 退出并显示信号 11 的原因,分段错误

在运行 Red Hat Linux (V6) 的生产服务器中,我经常从 bash 获得核心转储。这种情况每天发生几次到几十次。

总长度TR

解决:安装bash-debuginfo以从核心获取更多详细信息并找到导致崩溃的语句。

原因:在这种情况下,这是因为我的旧版本 bash 中未修复一个错误lists.gnu.org/archive/html/bug-bash/2010-04/msg00038.html2010 年 4 月针对 4.1 进行报告,并在 4.2 中修复(2011 年初发布)

细节
该服务器运行单个 Web 应用程序(apache + cgi-bin)和多个批次。 webapp cgi(C 程序)经常执行系统调用。

没有太多 shell 交互,因此核心转储可能是由某些服务或 Web 应用程序引起的,我必须知道是什么导致了此错误。

coredump 回溯有点枯燥(见下文)。

我怎样才能获得有关该错误的更多详细信息?我想知道什么是父进程链(完全详细),当前变量和环境,执行的脚本和/或命令是什么......

我启用了审核系统,但是有关此的审核线也有点枯燥。这是一个例子:

type=ANOM_ABEND msg=audit(1516626710.805:413350): auid=1313 uid=1313 gid=22107 ses=64579 pid=8655 comm="bash" sig=11

这是核心回溯:

    Core was generated by `bash'.
Program terminated with signal 11, Segmentation fault.
#0  0x000000370487b8ec in free () from /lib64/libc.so.6
#0  0x000000370487b8ec in free () from /lib64/libc.so.6
#1  0x000000000044f0b0 in hash_flush ()
#2  0x0000000000458870 in assoc_dispose ()
#3  0x0000000000434f55 in dispose_variable ()
#4  0x000000000044f0a7 in hash_flush ()
#5  0x0000000000433ef3 in pop_var_context ()
#6  0x0000000000434375 in pop_context ()
#7  0x0000000000451fb1 in ?? ()
#8  0x0000000000451c84 in run_unwind_frame ()
#9  0x000000000043200f in ?? ()
#10 0x000000000042fa18 in ?? ()
#11 0x0000000000430463 in execute_command_internal ()
#12 0x000000000046b86b in parse_and_execute ()
#13 0x0000000000444a01 in command_substitute ()
#14 0x000000000044e38e in ?? ()
#15 0x0000000000448d4e in ?? ()
#16 0x000000000044a1b7 in ?? ()
#17 0x0000000000457ac8 in expand_compound_array_assignment ()
#18 0x0000000000445e79 in ?? ()
#19 0x000000000044a264 in ?? ()
#20 0x000000000042ee9f in ?? ()
#21 0x0000000000430463 in execute_command_internal ()
#22 0x000000000043110e in execute_command ()
#23 0x000000000043357e in ?? ()
#24 0x00000000004303bd in execute_command_internal ()
#25 0x0000000000430362 in execute_command_internal ()
#26 0x0000000000432169 in ?? ()
#27 0x000000000042fa18 in ?? ()
#28 0x0000000000430463 in execute_command_internal ()
#29 0x000000000043110e in execute_command ()
#30 0x000000000041d6d6 in reader_loop ()
#31 0x000000000041cebc in main ()
~

更新:系统正在VMWare 处理的虚拟机中运行。

  • 什么版本的 bash? GNU bash,版本 4.1.2(1)-发布 (x86_64-redhat-linux-gnu)

  • 链接到 bash 的 libc 和其他库是什么版本?

ldd(GNU libc)2.12

(链接到 bash 的其他库是什么?是否有命令可以连续获取详细信息?

  • 这是在运行脚本或交互式 shell 时发生的,还是两者都发生?如果是脚本,它只发生在一个脚本上,还是在几个脚本上,或者任何脚本上?一般来说,你的 bash 脚本在执行什么类型的任务?你是否从其他进程中得到 seg 错误?你在服务器上运行过内存测试吗?它有 ECC RAM 吗?

正如我的问题中所述:我不知道,但它应该是由一些预定的脚本或交互式网络应用程序内部的一些系统调用引起的。它也可能是“脚本中的脚本”,就像这种结构一样:

myVar=$($(some command here ($and here too))

不过我觉得这个问题可能不是 RAM 的物理问题,因为没有其他随机崩溃,只有这个,而且我们还在 2 个独立的物理机上运行的 2 个独立的虚拟机上遇到了这个问题。

更新2:

从堆栈中我感觉问题可能与关联数组有关:

#1  0x000000000044f0b0 in hash_flush ()
#2  0x0000000000458870 in assoc_dispose ()
#3  0x0000000000434f55 in dispose_variable ()
#4  0x000000000044f0a7 in hash_flush ()

这类变量几乎存在于我们所有的自定义脚本中:有一个主脚本使用了一个库,其中包含我们系统的常用变量和函数。

我们几乎每一个脚本都源自该脚本。

答案1

我按照 gdb 的建议安装了 debuginfo 工具,然后得到了导致崩溃的表达式:

#20 0x0000000000457ac8 in expand_compound_array_assignment (
    var=<value optimized out>, 
    value=0x150c660 "$(logPath \"$@\")", flags=<value optimized out>
)

所以现在我知道问题是什么以及问题出在哪里。就我而言,它位于 .bashrc 中的函数中,根本原因是 Bash 中映射变量的错误重新定义:

declare -A myMap
local myMap=""

...
for key in "${!myMap[@]}"; do 
  echo ${myMap[$key]}
done    

该函数在子 shell 内调用,导致“分段错误”错误输出被隐藏。

答案2

这是一个典型的double free问题。hash_flush()在内存段上调用一次,0x000000000044f0a7然后在 处再次调用0x000000000044f0b0

您应该搜索所有调用hash_flush()并检查它们之前的关联数组值。

如果您在 shebang 行上启用日志记录和使用参数的组合,-x您将看到问题。

虽然我对 bash 不是 100% 确定,但它会从堆中清理内存(认为像 Perl、Python、PHP 和 Java 中的 GC 或 C/C++ 中的 free()、dealloc() 等)。

抱歉,这不是一个确定的解决方案,但我必须检查您的代码等。

相关内容