在前两篇中, 我们介绍了如何排查长时间运行的query, 以及如何在服务器上启用core generation。今天,我们来介绍下,如何收集进程的coredump进行排错。

1. 关于coredump的介绍

当程序异常或崩溃时,操作系统会中止进程,并将进程此时的内存中的内容拷贝到磁盘的指定目录下存储,生成一个core文件(是一个内存映像,同时加上调试信息),它记录了程序挂掉时详细的状态描述,以方便编程人员调试。

Greenplum什么情况下会生成coredump

当发生以下情况之一时, 就会产生coredump

  1. 由于硬件故障导致程序内部无法访问特定内容, 在某些情况下, 程序会发送终止信号给进程, 强制程序退出重启。
  2. 由于一些程序错误导致进程访问了错误的内存地址。
  3. 用户主动控制进程dump core文件, 这种操作一般用于排查故障, 这个之后会提到。

Greenplum集群的coredump在哪里?

如果需要让系统允许程序dump core文件, 那么需要开启一些其他参数, 比如需要在ulimit里将core的大小设置为足够大(或者不限制)

$ ulimit -a | grep core
core file size          (blocks, -c) unlimited

一般情况下, 在linux系统中, 可以通过以下参数确认core file的路径:

# sysctl kernel.core_pattern
kernel.core_pattern = /<directory>/core-%e-%s-%u-%g-%p-%t

更多的配置细节请参考《如何在服务器上启用core generation》

另外, 在一些情况下(比如排查之前我们上几篇文章中提到的query慢等问题), 用户需要主动在运行中的进程上收集coredump。这时就可以用到gcore 这个命令。注意这个命令是包含在gdb程序组件中, 如果需要使用的话需要现在操作系统上安装gdb包。以下以centos 举例:

### 安装gdb ###
$ sudo yum -y install gdb
​
### 使用gcore收集seg0上的con8对应进程的coredump,对应的进程号为27705 ###
$ ps -ef | grep con[0-9] | grep con8 | grep seg0
gpadmin   27705  27589  0 16:19 ?        00:00:00 postgres: 20000, gpadmin gpadmin 192.168.6.198(39012) con8 seg0 cmd6 MPPEXEC UTILITY
​
$ gcore 27705
...
Saved corefile core.27705

之后, 就会在当前目录生成一个名为 core.[pid] 的文件, 这个即为进程27705的coredump

2. 如何收集coredump

如果需要针对core文件做离线排错(offline troubleshooting)。除了core文件本身之外, 我们还需收集所有对应进程调用的库文件(library)。如果库文件有缺失, 那么通过gdb打开core文件的话将会有信息确认, 导致排错困难。

查找和收集库文件相对比较繁琐, 所幸, 我们用于收集日志的GPMT工具已经支持自动收集打包coredump和库文件的指令。详细信息可以参考之前的文章

举例:

$ ./gpmt packcore -cmd collect -core ~/core/core.27705
Creating temp directory ./packcore-core.27705
...
Packcore generated:
  packcore-core.27705.tar.gz

3. 如何快速手动收集所有文件

有时候我们无法使用gpmt工具收集文件。比如core文件本身有问题(gpmt无法正确解析binary), 或者我们的环境里有安全要求不允许上传执行文件到服务器。在这种情况下, 我们就可以通过以下方法手工收集文件了。

简单来说, 步骤如下:

  1. 通过gdb命令info shared library 来获取所有进程调用的库文件
  2. 将所有库文件复制到对应的目录。 (注: 有很多库文件是以软连接的形式存在的, 因此我们需要复制其对应的目标文件。)

我们编写了如下脚本来帮助您快速实现上述步骤:

#!/bin/bash
​
### 执行core文件的路径 ###
coreFile='/home/gpadmin/core/core.27705'
### GPHOME的路径 ###
GOHOME="/opt/greenplum-db"
​
unset PYTHONHOME
unset PYTHONPATH
unset LD_LIBRARY_PATH
​
for i in `gdb -ex "info sharedlibrary" -ex "quit" $GPHOME/bin/postgres $coreFile | grep "^0x" | awk '{print $NF}'`; do dir=`dirname $i`; file=`basename $i`; mkdir -pv .$dir ; cp -Lrpv $dir/$file .$dir/$file ;done
​
cp -rp $coreFile ./
cp -rp $GPHOME/bin/postgres ./

示例如下:

$ bash collect_core.sh
mkdir: created directory ‘./lib64’
‘/lib64/libz.so.1’ -> ‘./lib64/libz.so.1’
mkdir: created directory ‘./opt’
mkdir: created directory ‘./opt/greenplum-db’
mkdir: created directory ‘./opt/greenplum-db/./lib’
‘/opt/greenplum-db/./lib/libgpopt.so.3’ -> 
…
​
### result ###
$ ll
total 405188
-rw-rw-r-- 1 gpadmin gpadmin 351986816 Mar 15 16:22 core.27705
drwxrwxr-x 2 gpadmin gpadmin       293 Mar 16 11:16 lib64
drwxrwxr-x 4 gpadmin gpadmin        50 Mar 16 11:16 opt
-rwxr-xr-x 1 gpadmin gpadmin  62921216 Sep 26 00:14 postgres

4. 参考资料

在这里插入图片描述


Greenplum
153 声望66 粉丝

Greenplum 是全球领先的开源、多云大数据分析平台,被广泛运用于大规模商业智能和分析中,具有极高的稳定性。