需先确认kdump已启用:systemctl is-active kdump返回active,/proc/cmdline含crashkernel参数,且lsinitrd kdump.img包含kdump模块;再按时间戳取/var/crash下最新非空目录,检查vmcore或vmcore.xz,待kdump写入完成(核验kernel_version等标记)后归档。

如何确认系统已启用kdump并正常加载崩溃内核
没启用kdump,脚本再自动也没用——这是最常被跳过的前提。先检查kdump服务状态和crashkernel内核参数是否生效:
- 运行
systemctl is-active kdump,返回active才算服务在跑;若为inactive,需先执行systemctl enable --now kdump - 检查启动参数:
cat /proc/cmdline | grep crashkernel,必须看到类似crashkernel=128M(值因内存而异,但不能缺失) - 验证崩溃内核是否加载:
lsinitrd /boot/initramfs-$(uname -r)kdump.img | grep -q "kdump" && echo ok,无输出说明 initramfs 未包含 kdump 模块
常见坑:某些云主机或容器环境默认禁用 crashkernel,BIOS 中的 Secure Boot 也可能阻止 kdump initramfs 加载,此时需手动重装 dracut-kdump 并重建镜像。
崩溃转储路径与文件名规律必须硬编码进脚本
/var/crash/ 是默认路径,但实际子目录名带时间戳和内核版本,比如 /var/crash/127.0.0.1-2024-06-15-14:23:07/,里面才有 vmcore 和 vmcore-dmesg.txt。脚本不能只扫 /var/crash/*,得按时间排序取最新非空目录:
latest_dir=$(find /var/crash -maxdepth 1 -type d -name "[0-9]*" -printf '%T@ %p\n' 2>/dev/null | sort -n | tail -n1 | cut -d' ' -f2-)
注意点:
- 目录名可能含冒号(
:),find -name通配符无法匹配,必须用-printf+ 时间戳判断 - 有些发行版(如 RHEL 8+)默认把
vmcore压缩成vmcore.xz,脚本里得同时检查vmcore和vmcore.xz -
/var/crash可能被logrotate清理,确认/etc/logrotate.d/kdump中未配置rotate 0
自动归档脚本要绕过权限和锁文件问题
崩溃发生时,kdump 正在写入 vmcore,脚本若直接打包会遇到“文本忙”或权限拒绝。正确做法是等 kdump 完全退出、并检查锁标记:
-
kdump成功后会在目录下生成kernel_version和timestamp文件,可作为完成信号 - 用
fuser -v /var/crash检查是否有进程占用该目录,避免误操作 - 归档前加锁:
mkdir /var/crash/.archive_lock 2>/dev/null || exit 1,归档完再rmdir,防止并发触发多次 - 建议用
rsync -a --remove-source-files移动而非cp,既保留权限又释放磁盘空间
别用 inotifywait 监听目录创建——kdump 启动时就建好空目录,你监听到的不是“完成”,而是“开始”。
怎么让脚本在每次重启后自动检查并上报上次崩溃
Kernel Panic 发生后系统会硬重启,脚本没法“实时响应”,只能在下次启动时补救。推荐在 /etc/rc.d/rc.local 或 systemd service 的 ExecStartPre 阶段运行检测逻辑:
- 判断是否为 Panic 后首次启动:
last reboot | head -n1 | grep -q "system boot.*ago"不够准,改用dmesg -T | head -20 | grep -q "Kernel panic"更可靠 - 上报方式选轻量级:用
curl -X POST -F "file=@$vmcore_path" https://your-log-server/upload,避免引入 Python 或复杂依赖 - 务必加
timeout 300和重试逻辑,防止网络卡住阻塞开机流程
最容易被忽略的是 SELinux 上下文:RHEL/CentOS 默认禁止 rc.local 访问 /var/crash,得先运行 semanage fcontext -a -t public_content_t "/var/crash(/.*)?" 再 restorecon -Rv /var/crash。


















