前言:为什么要做这个启动盘,因为内核编译是很危险的,中间出了错系统则直接崩溃,然后就无法开机了,你将看到一个_在你的左上角闪烁。知道启动盘可以帮你从外置设备启动系统,能启动系统才能恢复系统。
一个可用的大于8G的USB启动盘,格式化为ext3、ext4或VFAT格式。
下载一个镜像文件,下文假设为ubuntu-16.04-64.iso。
一台可以使用的且装有Linux系统的主机(最好装有Centos或Ubuntu),并且具有root权限。
我的u盘只有一个分区,且为/dev/sdb1(以自己的为准。通过lsblk -l 查看)。
syslinux /dev/sdb1
为ubuntu-16.04-64.iso和USB存储设备创建挂载点:
mkdir /mnt/isoboot/ /mnt/diskboot
-o loop 选项用于创建一个伪设备,让他像设备块一样工作,此时这个目录可以看成一个块设备,如果不理解就可以看成插了一个U盘,里面有你烧录的系统。
mount -o loop ubuntu-16.04-64.iso /mnt/isoboot
mount /dev/sdb1 /mnt/diskboot
cp -r /mnt/isoboot/isolinux/* /mnt/diskboot
grep -v local的意思是排除保护local的字段:
grep -v local /mnt/isoboot/isolinux/isolinux.cfg > /mnt/diskboot/syslinux.cfg
完成以上步骤后执行:
umount /mnt/isoboot /mnt/diskboot
如果没有从U盘启动,可能需要进入bios界面调整启动顺序,把U盘调整为第一顺序,尝试在开机后迅速按F2、F10、F12(主机型号不同则不同)。
下载、配置并构建内核
配置内核前检查自己的U盘是否在有足够多的空间,最好留存4G以上的空间。
官网下有http和git两种下载方式,国内用户使用http下载较快,git更加官方,而且里面注明了内核的作者是谁,你可以下载到托瓦茨的内核。
HTTP https://www.kernel.org/pub/GIT https://git.kernel.org/ https://kernel.ubuntu.com/
使用http下载的读者点进去后进入linux目录,再进入kernel目录,再选择版本。
以4.0x为例:https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/
下载方式,wget:
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.0.5.tar.gz
下面有.gzip格式的和.bzip2格式的tar包,.gzip格式的使用命令(xyz代表版本号):
tar xvjf linux-x.y.z.tar.bz2
.zip格式:
tar xvzf linux-x.y.z.tar.gz
在编译之前,需要在你的操作机上安装一些软件。
build-essential用于在x86_64或arm64系统上编译内核,如果你是armhr(32位的arm架构),可能下面的内容不适合你。
- apt-get update && apt-get upgrade
- apt-get install build-essential
- apt-get install build-essential gcc
- apt-get install libncurses5-dev
- apt-get install binutils-multiarch
- apt-get install alien
- apt-get install ncurses-dev
以下选项根据需求勾选,新手不要随意乱动配置项,安装默认配置就可以了,保存后退出。
输入命令 -j 5代表开5个进程同时编译,速度比直接运行make要快很多。但是前提是你的CPU是多核多进程的,我的CPU4核,但是我写的5,意思是超频编译,实际上和4没什么区别,因为硬件条件摆在那。
编译需要至少半个小时,耐心等待。
make -j 5
编译完后,可以安装内核了。首先确保你为当前系统的重要数据做了备份。此外,需要把/boot下的内容复制到一个格式为FAT32的外部存储媒介上。(如u盘,格式化的方法请百度)
在内核的目录下执行,这个命令会把所有模块复制到当前的/lib/modules下对应的内核版本的子目录中:
make modules_install
这条命令将执行/sbin/installkernel文件,新内核会被复制到/boot/vmlinuz-{version},version为当前内核的版本号。实际上是一个软连接,链接到真实内核,如果/boot/vmlinuz-{version}存在,将会被覆盖并链接到新内核。旧内核会被保存为/boot/vmlinuz.old。
make install
你下载什么版本的就以什么结尾 vmlinuz-{version}。
cp -v arch/x86/boot/bzImage /boot/vmlinuz-4.0.5
RAM-随机存取存储器(random access memory)。
mkinitramfs -o /boot/initrd.img /lib/modules/4.0.5
该文件包含了一系列内核符号和对应地址:
cp System.map /boot/System.map-4.0.5
使System.map指向你新的内核map:
ln -sf /boot/System.map-4.0.5 /boot/System.map
如果你以上的步骤没有错,就可以使用新的内核了,如果重启失败,就需要用第一步准备的u启来引导启动,并且还原之前的配置,如果你备份了/boot目录,直接覆盖就可以恢复。
重启成功输入命令查看系统内核版本:
uname -a
如果我们想捕捉内核崩溃事件,可一旦系统被重新启动,由于没有创建该事件的日志,那么要捕获它就变得相当困难。我们可以使用Netconsole来解决这个问题。Netconsole是一个内核模块,它通过UDP协议记录内核消息。当不能记录到本地磁盘时,它可帮助调试问题。
在配置Netconsole之前,我们需要知道UDP数据包将被发送到的系统的MAC地址。该系统被称为接收方,可以与本机处于相同子网或者不同的子网。这两种情况描述如下:
第一种情况:接收方与本机在同一子网
使用ping 和arp命令,假设我的接受方为192.168.2.29。
第二种情况:不在同一子网
netstart -rn查看默认网关,图中为192.168.1.1,然后arp -n 192.168.1.1即可。网关就是我们要的MAC地址。
如果你正在使用Grub作为穷引导程序,它会默认启动内核的'quiet splash'选项,意思是闪屏,不显示启动过程。
先做备份,任何操作前做备份操作总没错:
- cp /etc/default/grub /etc/defautl/grub.backup
- vim /etc/default/grub
找到GRUB_CMDLINE_LINUX_DEFAULT="quietsplash"这一行,将该行替换为GRUB_CMDLINE_LINUX_DEFAULT="debugignore_loglevel"。
update-grub
将Netconsole模块添加到/etc/modules中,使它能在启动时被加载:
sh -c 'echo netconsole' >> /etc/modules
假设网卡为本地eth0,本地ip为192.168.1.11,网关为192.168.1.1(如果不在同一网段),接受方为192.168.2.29,刚才我们已经拿到了接受方的mac地址,
格式:netconsole=
- #接受方与发送方不在同一网段,发送者网关写本地IP
- sh -c 'echo options netconsole netconsole=6666@192.168.1.1/eth0,6666@192.168.2.29/ba:54:fc:df:f2:f0 > /etc/modprobe.d/netconsole.conf'
- #接受方与发送方在同一网段,发送者IP写本地IP
- sh -c 'echo options netconsole netconsole=6666@192.168.1.11/eth0,6666@192.168.1.29/ba:54:fc:df:f2:f0 > /etc/modprobe.d/netconsole.conf'
假设接受方,也就是用于监控发送方的主机ip为192.168.2.29,执行以下命令:
- netcat -l -u 192.168.2.29 6666 | tee ~/netconsole.log
- #也可以不带ip
- netcat -l -u 6666 | tee ~/netconsole.log
- #由于系统版本不同,上面命令报错则将-u改为-p
- netcat -l -p 6666 | tee ~/netconsole.log
输入命令,这样就可以监控内核的崩溃信息了。也可以查看~/netconsole.log。
dmesg | grep netcon