请求Ubuntu环境下内核二分调试的教程及自动化脚本
嘿,太懂你这种内核升级后软件突然罢工的糟心感了!之前我也碰过显卡驱动相关的内核问题,用git bisect来定位出问题的补丁绝对是最有效的办法。下面给你一套Ubuntu下的完整实操流程,还有我自己折腾出来的自动化脚本,帮你少走弯路快速定位根源。
一、前期准备工作
首先得把编译内核的环境搭好,打开终端装依赖:
sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev git ccache
装ccache是为了加速重复编译,毕竟内核编译慢得离谱,能省不少时间。然后把它加入环境变量:
echo 'export PATH="/usr/lib/ccache:$PATH"' >> ~/.bashrc source ~/.bashrc
接下来拉取Ubuntu的内核源码,比如你用的是Jammy(22.04),就拉对应的仓库:
git clone git://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/jammy cd jammy
如果是其他版本,把jammy换成你的系统代号(比如Focal是20.04)就行。
然后你得确定两个关键版本:
- Good版本:内核升级前一切正常的那个版本,比如
5.15.0-48-generic - Bad版本:出问题的当前内核版本,比如
5.15.0-50-generic
用下面的命令找到这两个版本对应的Commit Hash:
git log --oneline | grep "5.15.0-48" # 替换成你的good版本号 git log --oneline | grep "5.15.0-50" # 替换成你的bad版本号
记下这两个Hash值,比如good_hash和bad_hash。
二、手动二分调试流程
- 初始化二分:
git bisect start git bisect bad <bad_hash> git bisect good <good_hash>
Git会自动切换到两个版本中间的一个Commit,接下来开始编译。
- 编译内核:
先复制当前系统的内核配置,避免从头配置的麻烦:
cp /boot/config-$(uname -r) .config make olddefconfig
然后开始编译,用多线程加速(nproc是你的CPU核心数):
make -j$(nproc)
编译完成后安装模块和内核:
sudo make modules_install install sudo update-grub
- 测试重启:
重启系统,选择刚编译的内核(Grub菜单里的"Advanced options for Ubuntu"里找)。
重启后测试VSCode是否正常:
code --disable-extensions # 先排除扩展干扰
如果不需要加--disable-gpu就能正常运行,说明这个版本是好的,回到终端执行:
git bisect good
如果还是需要加参数或者崩溃,就执行:
git bisect bad
- 重复循环:
Git会自动切换到下一个中间版本,重复编译、重启、测试的步骤,直到Git定位到具体出问题的那个Commit。最后它会输出那个Commit的信息,你就能知道是哪个补丁搞的鬼了。
三、自动化脚本简化操作
手动反复编译重启太折磨人,写两个脚本帮你自动化这个过程:
1. VSCode测试脚本(test_vscode.sh)
这个脚本用来自动检测VSCode是否能正常启动:
#!/bin/bash # 关闭所有VSCode进程先 pkill code sleep 2 # 启动VSCode(不带--disable-gpu) code --disable-extensions & PID=$! # 等待5秒让它完全启动 sleep 5 # 检查进程是否存活:存活则正常,返回0;崩溃则返回1 if ps -p $PID > /dev/null; then kill $PID echo "Good: VSCode runs normally" exit 0 else echo "Bad: VSCode crashed or needs --disable-gpu" exit 1 fi
给脚本加执行权限:
chmod +x test_vscode.sh
2. 内核二分自动化脚本(bisect_auto.sh)
这个脚本用来自动编译内核,不过重启后的测试还需要手动触发,或者你可以把测试脚本加到开机启动里:
#!/bin/bash # 复制当前配置 cp /boot/config-$(uname -r) .config make olddefconfig # 编译,编译失败则让Git跳过这个版本 make -j$(nproc) || exit 125 # 安装内核和模块 sudo make modules_install install || exit 125 sudo update-grub || exit 125 echo "Kernel compiled and installed. Rebooting to test..." sudo reboot
加执行权限:
chmod +x bisect_auto.sh
然后用Git Bisect的自动运行功能:
git bisect run ./bisect_auto.sh
不过重启后,你需要手动运行test_vscode.sh,然后根据返回值执行git bisect good或git bisect bad,继续下一轮。如果想完全自动化,可以把测试脚本加到/etc/rc.local(Ubuntu 22.04需要先启用rc-local服务),让它开机自动运行并把结果写到文件里,下次启动后脚本读取结果自动标记。
四、一些注意事项
- 编译内核会占用大量磁盘空间(大概几十G),确保你的硬盘有足够空间。
- 每次编译前可以清理一下临时文件:
make clean或者make mrproper(后者会清空配置,慎用)。 - 如果遇到某个Commit编译失败,执行
git bisect skip让Git跳过这个版本。 - 测试时尽量关闭其他无关程序,避免干扰测试结果。
备注:内容来源于stack exchange,提问作者Martin

