Linux Kernel panic: Attempted to kill init 故障排查与修复实战

发布时间:2026/10/22 3:05:51
Linux Kernel panic: Attempted to kill init 故障排查与修复实战 1. 从一个凌晨的告警说起init进程被杀的现场还原那是一个再普通不过的运维夜班监控面板上突然跳出一台老业务机的红色告警。远程带外管理界面里屏幕上赫然停着这么一行字Kernel panic - not syncing: Attempted to kill init!后面跟着一串寄存器信息和调用栈光标不再滚动系统彻底僵死。这台机器跑的是CentOS 6上面还挂着几个老旧的内部服务重启是唯一的选择但重启之后能不能起来、为什么会这样才是真正要搞清楚的事。Attempted to kill init这个报错字面意思是试图杀死init进程。init是Linux用户空间的第一个进程PID固定为1它是所有其他进程的祖先。内核有一条铁律init进程不允许被杀死一旦init退出或被信号终止内核就会直接panic。所以这条报错本质上不是有人要杀init而是init进程自己异常退出了内核发现PID 1没了只能崩溃。理解这一点非常关键因为它决定了排查方向。很多人看到kill init以为是误操作执行了kill -9 1实际上绝大多数情况下是init在启动过程中遇到了无法继续的错误自己退出了。常见诱因包括根文件系统挂载失败、/sbin/init二进制损坏或被替换、关键配置文件如/etc/inittab、/etc/fstab写错、磁盘坏道导致读取失败、以及升级glibc或内核后ABI不兼容等。我处理过的这类故障里CentOS 6和CentOS 7的表现还有明显差异。CentOS 6用的是传统的SysV init/sbin/init指向upstartCentOS 7换成了systemd/sbin/init是systemd的软链。两者在启动流程、依赖的配置文件、以及报错前后的日志线索上都不一样所以排查手法要分开对待。下面我会把整个处理链路拆开讲从现场判断、救援模式进入、根因定位到修复验证和后续加固尽量还原我当时一步步的操作。提示遇到Kernel panic时第一件事不是急着重启而是尽可能把屏幕上的调用栈、报错行、以及最后加载的模块信息拍照或记录下来。重启之后这些信息就没了而它们往往是定位问题的唯一线索。2. 先别急着重启panic现场能抢救出哪些关键信息2.1 屏幕上的调用栈到底在说什么Kernel panic的输出通常分几段第一行是panic的原因描述接着是CPU: X PID: 1 Comm: init这样的进程信息然后是Call Trace调用栈最后是Kernel Offset和一堆寄存器值。对Attempted to kill init这个场景我最关注的是两处。第一处是Comm字段。如果显示Comm: init说明确实是init进程本身出了问题如果显示的是别的进程名但PID是1那可能是init被替换成了别的程序。第二处是Call Trace里出现的函数名比如do_exit、panic、mount_block_root、prepare_namespace这些。如果调用栈里出现mount_block_root或prepare_namespace基本可以锁定是根文件系统挂载阶段出的问题init还没来得及真正跑起来就挂了。还有一种情况是调用栈里出现load_elf_binary或search_binary_handler这通常意味着/sbin/init这个可执行文件本身有问题——要么被损坏要么依赖的动态库找不到导致内核加载init失败。2.2 带外管理与串口日志的取舍如果机器有IPMI、iDRAC这类带外管理能直接看到屏幕内容那是最好的。如果没有就得靠串口重定向。CentOS 6/7都可以在GRUB里加consolettyS0,115200把内核输出重定向到串口配合另一台机器用串口工具抓日志。但故障已经发生时这些配置往往来不及加所以更现实的做法是重启进入GRUB菜单在kernel行临时追加参数让启动过程更啰嗦。我常用的临时参数组合是consoletty0 consolettyS0,115200 ignore_loglevel initcall_debugignore_loglevel让所有级别的内核消息都打印出来initcall_debug会显示每个初始化调用的耗时和结果。这两个参数加上之后启动卡在哪一步、哪个驱动或子系统出问题会清楚很多。对于根文件系统相关的故障还可以加rootdelay10给磁盘留出更长的识别时间有些老机器磁盘初始化慢不加这个参数就会因为找不到根分区而panic。2.3 判断是CentOS 6还是CentOS 7的快速方法在GRUB界面里CentOS 6的内核条目通常写着CentOS (2.6.32-xxx.el6.x86_64)CentOS 7则是CentOS Linux (3.10.0-xxx.el7.x86_64)。从内核版本号就能一眼区分。这个判断很重要因为接下来进救援模式后CentOS 6和7的修复命令、配置文件路径、以及initramfs的重建方式都不同。另外CentOS 6的GRUB是0.97版本菜单里按e编辑CentOS 7是GRUB2按e编辑改完按CtrlX启动。操作习惯上也有区别GRUB2支持grub2-mkconfig重新生成配置而GRUB 0.97是直接改/boot/grub/grub.conf。这些细节在救援模式下会直接影响修复效率。3. 进入救援模式CentOS 6与7的操作差异3.1 用安装介质引导进入rescue修复这类故障标准做法是用对应版本的安装ISO引导选择Rescue installed system。CentOS 6和7的救援模式界面不同但核心逻辑一致它会尝试把你的根文件系统挂载到/mnt/sysimage下让你在一个临时的shell里操作。CentOS 6的救援模式会先问你语言、键盘然后问是否要启动网络接着它自动探测硬盘上的系统并挂载。CentOS 7的救援模式流程类似但多了一步它会问你是要Continue还是Read-only mount还是Skip。如果怀疑文件系统有损坏先选Read-only挂载用fsck检查完再重新挂载为读写。挂载完成后救援环境会提示你执行chroot /mnt/sysimage进入原系统环境。这一步非常关键因为只有chroot之后你执行的grub-install、mkinitrd、dracut这些命令才会作用到真正的系统上而不是救援环境本身。3.2 如果根分区根本挂不上怎么办有些情况下救援模式也挂不上根分区提示Unable to mount或者直接报文件系统错误。这时候不要慌先手动确认磁盘和分区状态lsblk fdisk -l /dev/sda blkidlsblk看块设备树fdisk -l看分区表blkid看文件系统类型和UUID。如果blkid读不出某个分区的UUID或者fdisk -l报分区表错误那问题可能出在分区表或文件系统超级块上。文件系统损坏的话用fsck修复。注意fsck必须在分区未挂载的状态下执行否则可能造成二次损坏fsck -y /dev/sda1-y表示对所有询问自动回答yes。如果是ext4文件系统fsck.ext4会更明确。修复完成后重新尝试挂载。如果分区表本身坏了那就得用testdisk或gdisk这类工具尝试恢复分区表这一步风险较高操作前务必确认有没有备份。3.3 chroot之后的第一批检查命令成功chroot进原系统后我会按固定顺序做一批检查快速缩小问题范围# 检查init文件是否存在、是否可执行 ls -l /sbin/init file /sbin/init # 检查关键配置文件 cat /etc/fstab cat /etc/inittab # CentOS 6 ls -l /etc/systemd/system/default.target # CentOS 7 # 检查磁盘空间和inode df -h df -i # 检查最近修改过的文件 find /etc /sbin /lib -mtime -3 -type fls -l /sbin/init看它是不是一个正常的软链或二进制。CentOS 6上它通常指向/sbin/upstart或本身就是init二进制CentOS 7上它指向/usr/lib/systemd/systemd。如果这个链接断了或者指向了一个不存在的文件那init自然起不来。/etc/fstab是重灾区。如果里面写了一个不存在的UUID或者把根分区的挂载选项写错了比如把defaults写成了noauto系统启动时就会挂载失败进而导致init无法继续。我遇到过好几次都是因为有人手动改fstab加了一块数据盘结果UUID写错重启就panic了。df -h和df -i用来排除磁盘满和inode耗尽。根分区满了会导致init无法写入必要的运行时文件inode耗尽同理。这两种情况在日志服务器上特别常见。4. 根因定位五类高频诱因的排查路径4.1 fstab配置错误导致的挂载失败这是我最常遇到的诱因没有之一。典型场景是运维人员添加了一块新磁盘用blkid拿到UUID后写进/etc/fstab但复制UUID时多了一个字符或者少了一个字符或者把/dev/sdb1写成了/dev/sdb2。重启后系统在挂载阶段找不到对应设备如果这个错误条目排在根分区之前或者根分区的挂载依赖它就会直接panic。排查方法很直接在救援模式下打开/etc/fstab逐行核对UUID。用blkid列出当前所有分区的真实UUID一一比对。对于不确定的条目可以先注释掉行首加#只保留根分区和/boot然后重启测试。能起来就说明是fstab的问题再逐条恢复找出罪魁祸首。注意修改fstab后不要直接重启生产机。可以先用mount -a测试这个命令会尝试挂载fstab里所有未挂载的条目如果有错误会立即报出来比重启安全得多。4.2 initramfs损坏或与内核不匹配initramfsCentOS 6叫initrdCentOS 7叫initramfs是内核启动时加载的临时根文件系统里面包含了挂载真正根分区所需的驱动和脚本。如果initramfs损坏或者里面的驱动和当前内核版本不匹配就会出现找不到根设备然后panic的情况。判断方法在GRUB里看内核版本然后检查/boot下对应的initramfs文件是否存在、大小是否正常。CentOS 6的路径是/boot/initramfs-2.6.32-xxx.el6.x86_64.imgCentOS 7是/boot/initramfs-3.10.0-xxx.el7.x86_64.img。如果文件大小为0或者明显偏小那就是损坏了。重建方法分版本# CentOS 6 mkinitrd -f /boot/initramfs-$(uname -r).img $(uname -r) # CentOS 7 dracut -f /boot/initramfs-$(uname -r).img $(uname -r)注意在救援模式下uname -r显示的是救援环境的内核版本不是原系统的。所以要么手动指定原系统的内核版本号要么先chroot再执行。我一般选择chroot后执行避免版本号搞错。4.3 /sbin/init被替换或损坏这种情况相对少见但一旦发生就很棘手。可能的原因包括恶意软件替换了init、磁盘坏道导致init二进制读取错误、或者手动升级systemd/upstart时中断导致文件不完整。检查方法# 查看init的完整性 rpm -V upstart # CentOS 6 rpm -V systemd # CentOS 7rpm -V会校验包内所有文件的MD5、大小、权限等。如果输出里有/sbin/init相关的行前面标记为S大小变化或5MD5变化说明文件被改过。这时候最稳妥的做法是从同版本的正常机器上拷贝一份或者用yum reinstall重装对应的包。如果系统还能联网救援模式下可以配置网络直接yum reinstall systemd或yum reinstall upstart最省事。不能联网的话就得从安装ISO里提取RPM包手动安装mkdir /tmp/cdrom mount /dev/cdrom /tmp/cdrom rpm -ivh --force /tmp/cdrom/Packages/systemd-xxx.rpm4.4 磁盘坏道与文件系统损坏老机器上磁盘坏道是绕不开的话题。当坏道恰好落在init二进制、关键库文件、或者文件系统元数据区域时就会导致读取失败进而引发panic。判断方法用smartctl看磁盘健康状态用dmesg看有没有I/O错误记录。在救援模式下smartctl -a /dev/sda | grep -i reallocated\|pending\|uncorrectable dmesg | grep -i error\|fail\|bad如果Reallocated_Sector_Ct或Current_Pending_Sector数值很高说明磁盘已经在带病工作尽快备份数据并更换磁盘。文件系统层面的损坏用fsck修复但要注意fsck只能修复文件系统结构无法恢复坏道上的数据。如果坏道正好在关键文件上修复后文件可能变成空文件或乱码这时候只能从备份恢复。4.5 内核与用户空间ABI不兼容这种诱因通常出现在手动升级内核或glibc之后。比如有人为了支持新硬件手动编译了一个新内核但没重新编译对应的initramfs或者新内核的配置和原有用户空间的系统调用不兼容导致init启动时崩溃。判断线索panic发生前如果能看到Kernel panic之前有segfault at ...或者init: symbol lookup error之类的信息基本可以确定是ABI问题。解决方法是在GRUB里选择旧内核启动进入系统后重新配置新内核或者回退到稳定版本。在GRUB界面选择旧内核的方法CentOS 6在启动时按任意键进入菜单用上下键选择带旧版本号的条目CentOS 7在GRUB2菜单里选Advanced options然后选旧内核。进入系统后用grub2-set-default或修改/etc/default/grub把默认启动项改回旧内核。5. 修复实操从救援模式到正常启动的完整链路5.1 修复fstab并验证挂载假设排查后确认是fstab里多了一行错误的UUID。修复步骤# 进入救援模式并chroot chroot /mnt/sysimage # 备份原fstab cp /etc/fstab /etc/fstab.bak # 编辑fstab注释掉可疑行 vi /etc/fstab # 测试挂载 mount -a # 如果没有报错退出chroot并重启 exit rebootmount -a这一步非常重要它能在重启前验证fstab的正确性。如果mount -a报错说明还有问题继续修改直到通过为止。重启后如果系统正常起来再把注释掉的行逐条恢复每恢复一条就mount -a测试一次找出真正有问题的那条。5.2 重建initramfs的完整流程如果是initramfs损坏修复流程如下# 救援模式chroot chroot /mnt/sysimage # 确认/boot分区已挂载 mount | grep /boot # 如果没挂载手动挂载 mount /dev/sda1 /boot # 查看当前内核版本 ls /lib/modules/ # 重建initramfs以CentOS 7为例 dracut -f /boot/initramfs-3.10.0-1160.el7.x86_64.img 3.10.0-1160.el7.x86_64 # 确认文件生成且大小正常 ls -lh /boot/initramfs-3.10.0-1160.el7.x86_64.img重建完成后还要检查GRUB配置里指向的initramfs路径是否正确。CentOS 7的GRUB2配置在/boot/grub2/grub.cfg可以用grub2-mkconfig -o /boot/grub2/grub.cfg重新生成。CentOS 6的配置在/boot/grub/grub.conf手动确认initrd行指向的文件名和实际文件一致。5.3 修复init二进制与依赖库如果确认是init文件损坏从同版本正常机器拷贝是最快的方法。但要注意拷贝时保持权限和属主一致# 在正常机器上 scp /sbin/init user故障机IP:/tmp/init # 在故障机救援模式下 chroot /mnt/sysimage cp /tmp/init /sbin/init chmod 755 /sbin/init chown root:root /sbin/init如果是依赖库损坏比如libsystemd.so同样从正常机器拷贝对应的.so文件到/lib64或/usr/lib64下然后执行ldconfig刷新库缓存。拷贝前先用ldd /sbin/init查看它依赖哪些库确保所有依赖都完整。5.4 用旧内核启动并锁定稳定版本如果新内核有问题先用旧内核进入系统然后做两件事一是把默认启动项设为旧内核二是把有问题的内核包卸载或排除更新。CentOS 7设置默认启动项# 查看所有可用启动项 awk -F\ $1menuentry {print $2} /boot/grub2/grub.cfg # 设置默认启动项索引从0开始 grub2-set-default 2 # 确认设置 grub2-editenv listCentOS 6直接编辑/boot/grub/grub.conf把default的值改成对应旧内核的索引号。改完后重启验证确认系统从旧内核正常启动。为了防止后续yum update又把有问题的内核装回来可以在/etc/yum.conf里加excludekernel*或者用yum versionlock锁定内核版本。不过长期来看还是应该找到新内核的问题并解决而不是一直停留在旧版本。6. 修复之后的加固让panic不再重演6.1 fstab的规范化管理fstab出问题往往是因为手动编辑时不够谨慎。我的做法是所有fstab修改都先备份改完必须mount -a验证验证通过才重启。另外对于数据盘尽量用UUID而不是设备名因为设备名可能因为磁盘顺序变化而改变。但UUID也要仔细核对复制后至少检查两遍。还有一个技巧在fstab里给非关键挂载点加上nofail选项。这样即使这个挂载点失败系统也能继续启动不会因为一块数据盘的问题导致整个系统panic。nofail在CentOS 7上支持良好CentOS 6的内核也支持但需要确认util-linux版本。UUIDxxxx-xxxx /data ext4 defaults,nofail 0 06.2 保留一个可用的旧内核每次内核更新后不要立即删除旧内核。至少保留一个已知可用的旧内核作为后备。CentOS 7默认会保留三个内核但有些人为了省空间会手动清理。我的建议是在确认新内核稳定运行至少一周后再清理更旧的内核而且永远保留最近一个旧版本。检查已安装内核rpm -qa | grep kernel如果发现只剩一个内核赶紧装回一个旧版本yum install kernel-3.10.0-1160.el76.3 配置kdump与串口日志kdump能在内核panic时把内存转储到磁盘事后可以用crash工具分析。CentOS 7默认安装并启用kdump但需要确认预留内存足够。CentOS 6需要手动安装kexec-tools并配置。# 检查kdump状态 systemctl status kdump # 查看预留内存 grep crashkernel /proc/cmdline串口日志对于没有带外管理的机器尤其重要。在GRUB里永久加上consolettyS0,115200并配置/etc/securetty允许串口登录这样即使系统panic也能从串口另一头看到完整输出。6.4 定期检查磁盘健康对于老机器定期跑smartctl检查磁盘健康是必要的。可以写个简单的脚本每周跑一次发现Reallocated_Sector_Ct增长就告警。#!/bin/bash for disk in /dev/sd[a-z]; do smartctl -H $disk | grep -q PASSED || echo Disk $disk health check failed smartctl -A $disk | awk /Reallocated_Sector_Ct/ {if ($10 0) print Disk $disk has reallocated sectors: $10} done这个脚本可以放进cron输出通过邮件或监控系统告警。磁盘坏道是渐进的过程早发现早更换能避免很多半夜的panic。7. 几个容易踩的坑和我的个人体会第一个坑是在救援模式下忘记挂载/boot就重建initramfs。dracut或mkinitrd默认输出到/boot如果/boot没挂载文件会写到救援环境的临时文件系统里重启后原系统的initramfs根本没变。所以执行重建前一定先mount | grep /boot确认。第二个坑是chroot后执行grub-install时设备名搞错。比如系统盘是/dev/sda但救援模式下U盘变成了/dev/sda硬盘变成了/dev/sdb。这时候执行grub-install /dev/sda就把GRUB装到U盘上了。所以操作前先用lsblk确认设备名别想当然。第三个坑是用fsck修复时没加-y导致卡在交互询问。有些fsck版本在遇到需要确认的修复项时会停下来等输入如果是在脚本或远程会话里就会一直卡住。加-y自动确认或者加-p以安全模式自动修复。第四个坑是修改fstab后直接reboot而不是先mount -a。这个前面强调过了但真的很多人犯。mount -a几秒钟的事能省掉一次panic和半小时的救援。我个人的体会是Attempted to kill init这个报错虽然看起来吓人但排查思路其实很清晰先判断是挂载问题还是init本身问题再分版本用对应的工具修复。真正花时间的不是修复动作而是定位根因。所以现场信息的保留、救援模式的熟练操作、以及对CentOS 6和7差异的清楚认知这三样东西决定了你处理这类故障的速度。平时多演练几次救援模式真出事的时候就不会手忙脚乱。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询