问题定位及定位方法
当系统出现异常情况时,很多时候没有办法立刻确定是哪个程序、哪个模块出现了问题,这就需要我们通过一些手段对问题进行一个定界,然后再通过一些工具对问题进行具体的定位。
日志系统
查看日志是问题定界时最直接的手段,在百度Linux服务器操作系统 V5.0中,有多种查看日志的方法。
- rsyslog
rsyslog是一个传统的linux日志工具,在基于systemd的百度Linux服务器操作系统 V5.0系统中被保留。rsyslog日志文件记录了系统中包括内核、服务和其它应用程序等在内的运行信息, rsyslog的配置文件为 /etc/rsyslog.conf , 大多数日志文件都位于 /var/log/ 目录中。当然,除了rsyslog管理的日志,部分通过yum安装的系统服务或者第三方应用,也会默认把日志记录在“/var/log"目录中,不过这些日志不是由rsyslogd服务来记录和管理的,而在各个服务或应用使用自己的日志管理文档来记录自身日志。
| 日志名称 | 日志路径 | 日志功能 | 备注 |
|---|---|---|---|
| 定时任务日志 | /var/log/cron | 记录了系统定时任务相关的日志。 | - |
| 内核日志 | /var/log/dmesg | 记录了系统在开机时内核自建的信 息。也就是使用dmesg命令直接查看内核自检信息。 | - |
| 登录失败日志 | /var/log/btmp | 记录错误登录的日志。这个文件是二进制文件,不能直接用vi查看,而是要用lastb命令查看 | 如果有人攻击你的电脑就这个文件就会有大量的日志信息。 |
| 最后登录日志 | /var/log/lastlog | 记录系统中所有用户最后一次的登录时间的日志。这个文件也是二进制文件,不能直接vi, 而要用lastlog命令查看。 | - |
| 邮件日志 | /var/log/maillog | 记录邮件信息 | |
| 系统日志 | /var/log/messages | 记录系统重要信息的日志。这个日志文件中会记录Linux 系统的绝大多数重要信息,如果系统出现问题时,首先要检查的就应该是这个日志文件。 | 该日志文件默认还会记录一些服务日志。 |
| 安全日志 | /var/log/secure | 记录验证和授权方面的信息,只要涉及账户和密码程序的都会记录。比如说系统的登录,ss 的登录,su切换用户,sudo授权,甚至添加用户和修改用户密码都会记录在这个日志文件中。 | - |
| 登录日志 | /var/log/wtmp | 永久记录所有用户的登录,注销信 息,同时记录系统的启动,重启,关机时间。同样这也是一个二进制文 件,不能直接vi打开,而需要last命令来查看。 | - |
| 当前登录日志 | /var/run/utmp | 记录当前已经登录的用户的信息,这个文件会随着用户的登录和注销而不断变化,只记录当前登录用户的信 息。同样这个文件也不能直接用vi打开,而是要用, w,who,users等命令来查询。 | - |
- systemd 日志
systemd采用Journald系统服务来收集和管理系统日志,它可以收集来自内核,启动过程的早期阶段,标准输出,系统日志,以及服务,守护进程启动和运行期间的错误的消息。
Journald系统主要由三个主要的系统日记服务组件组成:
- 守护进程:systemd日志服务由systemd-journald守护程序处理。
- 配置文件:日志服务的配置在/etc/systemd/journald.conf里面设置。
- 日志搜索程序:用于搜索日志文件的程序是journalctl。
Journald支持不同的类型存储,可以通过修改/etc/systemd/journald.conf文件控制存 储类型值,在[Journal]字符串下面可以修改存储类型。
1[Journal]
2Storage=auto
- 如果为volatile,则日志数据将仅存储在内存中,即在/run/log/journal目录下,系 统重启后数据会被删除。
- 如果是persistent,则数据将会存储在磁盘上,即/var/log/journal目录下,并且在 早期引导阶段磁盘不可写的时候把数据保存到/run/log/journal目录下。
- auto值意味着把日志数据存储在/var/log/journal/目录中。但是该目录必须已经存 在并且设置了适当的权限。如果不存在,则日记数据将存储在易失性/run/log/ journal/目录中。
- none关闭所有存储,所有接收到的日志数据将被丢弃。
Storage支持的值为volatile,persistent,auto和none,默认是auto,所有值的含义如下。
journalctl使用:
1# 查看所有日志
2journalctl
3# 查看内核日志,与dmesg功能相同
4journalctl -k
5# 查看系统本次启动日志
6journalctl -b journalctl -b -0
7# 查看上一次启动日志,需要配置日志持久存储
8journalctl -b -1
9# 查看指定时间的日志
10journalctl --since="2022-12-20 12:22:02" journalctl --since "5 min ago"
11journalctl --since yesterday
12journalctl --since "2022-01-01" --until "2022-12-31 18:01" journalctl --since 10:30 --until "3 hour ago"
13# 显示尾部指定行数的日志
14journalctl -n 20
15# 实时滚动显示最新日志
16journalctl -f
17# 查看指定服务的日志
18journalctl -u docker.service
19# 查看指定级别及以上的日志。 0:emerg 1:alert 2:crit 3:err 4:warning 5:notice 6:info 7:debug journalctl -b -1 -p err
定位方法
为了能定位到系统问题产生的原因,我们通常要借助一些工具,用户态的coredump和内核态的kdump就是常用的两种手段。
- coredump
coredump即核心转储,当linux系统中程序运行发生异常退出时,系统会把程序运行时的内存、寄存器状态、堆栈指针、内存管理信息以及函数调用堆栈等信息存储在一个core文件中,供技术人员分析定位使用。使用coredump的方法如下。
- 配置coredump:
一般情况下系统默认关闭了coredump产生,通过命令ulimit -c 查看:

如果结果为0,表示系统限制core文件的大小为0,即使程序发生core dump了, 也不会有core文件留下。我们需要让core文件能够产生:
1# ulimit -c unlimited #表示不限制core文件大小
2# unlimit -c 1024 #设置core最大大小,单位为块,一块默认为512字节
此时系统已经可以正常产生core文件了,但是为了便于找到core文件,还需要配 置core文件的存储位置,一般有两种配置方式。
a. 临时生效方式:
1echo "/var/core/core-%e-%p-%s-%t-%u" > /proc/sys/kernel/core_pattern # 具体参数表示如下:
2%e 所dump的文件名
3%p 所dump的进程PID
4%s 导致本次coredump的信号
5%E 进程执行所在目录
6%c 转储文件的大小上限
7%g 所dump的进程的实际组ID
8%h 主机名
9%t 转储时刻(由1970年1月1日起计的秒数)
10%u 所dump进程的实际用户ID
b. 永久生效方式:
为了使core dump的配置永久生效,可以将以上配置写入系统配置文件etc/ sysctl.conf,并执行命令sysctl -p生效
1kernel.core_pattern = /var/core/core-%e-%p-%s-%t-%u kernel.core_uses_pid=0
2## 说明
3core_uses_pid设置pid作为文件扩展名
41:添加pid作为扩展名,生成的core文件名称为core.pid
50:不添加pid作为扩展名,生成的core文件名称为core
- gdb分析core文件
gdb是GNU开源组织发布的一个强大的UNIX系统下的程序调试工具,我们可以使用gdb工具对core文件进行调试,可以使用如下命令启动调试:
1# gdb 程序文件名 core文件名
| 命令 | 简写 | 作用 |
|---|---|---|
| File | f | 装入想要调试的可执行文件 |
| Cd | - | 改变当前目录 |
| pwd | - | 查看当前目录 |
| run | r | 执行当前被调试程序 |
| Kill | k | 停止正在调试的程序 |
| List | l | 列出正在调试的程序的源代码 |
| break | b | 设置断点 |
| tbreak | tb | 设置临时断点。执行一次之后断点立即消失 |
| watch | w | 设置监视点,监视表达式的值 |
| awatch | aw | 设置读写监视点。当表达式被读或写时程序挂起 |
| rwatch | rw | 设置读监视点 |
| Next | n | 执行下一条源代码,但是不进入函数内部 |
| Step | s | 执行下一条源代码,进入函数内部 |
| display | d | 在程序每次停止运行时显示表达式的值 |
| info break | info b | 显示当前断点列表 |
| info files | - | 显示调试文件的信息 |
| info func | info f | 显示所有函数名 |
| info local | info l | 显示当前函数所有局部变量的信息 |
| info prog | info p | 显示调试程序的执行状态 |
| p | 显示表达式的值 | |
| delete | d | 删除断点。指定断点号码则删除指定断点,否则删除所有断点 |
| Shell | - | 执行shell 命令 |
| make | - | 不退出gdb而重新编译生成可执行文件 |
| backtrace | bt | 用于回溯函数调用栈 |
| Quit | q | 退出gdb |
- Kdump
kdump是在系统崩溃、死锁或死机时用来转储内存运行参数的一个工具和服务,是一种新的crash dump捕获机制,用来捕获kernel crash 的时候产生的crash dump。kdump机制在Linux2.6.38被ARM平台内核主线接纳,它是通过两个内核实现的,在正常使用的系统内核外,通过启动另一个捕获内核来捕获系统内核信息的方法,来进行转储操作。具体流程下图所示:

- 系统内核正常启动,包括硬件自检,bootloader加载等常规过程,并预留内存空间给捕获内核。
- 加载捕获内核到预留内存空间。
- 系统发生崩溃,触发panic,捕获内核启动。捕获内核采用的是kexec机制,可以跳过硬件自检的环境,快速启动内核。
- 捕获内核通过/proc/vmcore内存镜像文件,收集系统内核信息。
- 将系统内核信息经过压缩,生成转储文件,写到磁盘中。
对vmcore的分析是分析机器宕机原因的一个十分重要的手段。要分析vmcore,现在通常采用的就是crash的分析。在安装crash以后,还需要安装相应的debuginfo等带有符号信息的vmlinux文件才能调试相应的vmcore。一般可以通过安装相应的包(kernel- debuginfo-common-$(uname -r))来完成相应文件的安装。要注意的是,需要安装kernel-debuginfo-common以及kernel-dubuginfo这两个包,而kernel-dubuginfo又是依赖与kernel-dubuginfo-common这个包的。除了使用安装包安装,还可以通过编译源码的方式来获取vmlinux。
- 配置kdump
百度Linux服务器操作系统 V5.0默认开启kdump,通过命令systemctl status kdump查看kdump服务是否开启。如果没有启动kdump服务,则按如下步骤进行配置:

- 安装kdump、crash
1# yum install -y kernel-debuginfo-$(uname -r) kexec-tools systemctl enable kdump
2# systemctl start kdump
3# systemctl status kdump
- 配置kdump预留内存
为捕捉内核预留内存,编译/etc/default/grub,修改或添加GRUB_CMDLINE_LINUX变量中crashkernel参数(如crashkernel=1024M)
- 更新grub
1# bios+mbr启动
2# grub2-mkconfig -o /boot/grub2/grub.cfg # uefi+gpt启动
3# grub2-mkconfig -o /boot/efi/EFI/百度Linux服务器操作系统 V5.0/grub.cfg
- 验证kdump
使用命令迫使系统崩溃:echo c > /proc/sysrq-trigger,等系统重启后,检查在/var/crash目录下生成的vmcore和vmcore-dmesg.txt即可。

- 配置内核panic捕捉参数
只有发生内核panic,才能触发kdump机制,当内核发生一些死锁,系统并不会重启,只会卡死。这也意味着,这种情况下并不会造成内核panic。所以有时候需要构造条件使内核panic,这样才能触发kdump机制,生成vmcore文件。内核提供了多种场景构造panic:
a.进程出现hang时引发panic:
1# echo 1 > /proc/sys/kernel/hung_task_panic
b.进程hangtask机制超时时间:
1# echo 60 > /proc/sys/kernel/ hung_task_timeout_secs
c.软锁(soft lockup)触发panic:
1# echo 1 > /proc/sys/kernel/softlockup_panic
d.设置kernel遇到OOM触发panic:
1# echo 1 > /proc/sys/vm/panic_on_oom
e.设置内核中出现警告产生panic:
1# echo 1 > /proc/sys/kernel/panic_on_warn
输入上面的配置,相关配置只生效一次,重启后失效。如需要重启自动配置,可将下列参数写入etc/sysctl.conf文件,并执行命令sysctl -p生效。
1kernel.hung_task_panic=1
2kernel.hung_task_timeout_secs=60
3kernel.softlockup_panic=1
4vm.panic_on_oom=1
5kernel.panic_on_warn=1
- crash分析kdump
crash 是由 Dave Anderson 开发和维护的一个内存转储分析工具,广泛应用于内核问题定位。crash是和kdump工具配套使用,用于解析kdump生成的vmcore文件。
crash的安装非常简单,在百度Linux服务器操作系统 V5.0上可以直接用yum进行安装:
1# yum install -y crash
如果已经有了一个vmcore,那么需要找到该vmcore内核版本对应的具有调试信息的内核镜像,然后执行如下命令即可进入调试时环境:
1# crash vmlinux vmcore
进入调试环境后,crash调试的命令格式为:
1(crash) command *args ////进入调试会出现(crash),command是需要执行的调试命令,*args是部分调试命令需要的参数
常用的命令和用途如下:
| 命令 | 作用 |
|---|---|
| bt | 打印函数调用栈信息 |
| log | 打印系统消息缓冲区,如log | tail -n 30 |
| ps | 显示进程的状态,>表示活跃的进程, 如ps | grep RU |
| dis | 对给定函数或者地址进行反汇编,如dis -l [func | addr] |
| whatis | 搜索数据或者类型的信息,如: whatis [struct | union | typedef | symbol] |
| sym | 转换虚拟地址为符号 |
评价此篇文章
