我的電腦配置了雙硬盤:一塊固態硬盤(sda)安裝 Windows 7,另一塊機械硬盤(sdb)安裝 Ubuntu 和 CentOS 兩個 Linux 發行版。系統啟動由 sdb 上 Ubuntu 的 GRUB 2 管理,負責引導選單中選擇不同作業系統啟動。
昨晚我在 sdb 硬盤中間新增了一個分區(sdb6),導致後續所有邏輯分區編號全部後移。具體變化如下:
/dev/sdb8,變更為 /dev/sdb9/dev/sdb1,編號未變,故仍能正常啟動Disk /dev/sdb: 500.1 GB, 500107862016 bytes ... Device Boot Start End Blocks Id System /dev/sdb1 2048 125829119 62913536 83 Linux /dev/sdb2 125829246 970502711 422336733 f W95 Ext'd (LBA) /dev/sdb5 125829248 221983352 48077052+ 7 HPFS/NTFS/exFAT /dev/sdb6 221983424 228274807 3145692 b W95 FAT32 ← 新增分區 /dev/sdb7 228274872 518603944 145164536+ 7 HPFS/NTFS/exFAT /dev/sdb8 518604008 782021941 131708967 7 HPFS/NTFS/exFAT /dev/sdb9 782024704 918054911 68015104 83 Linux ← CentOS 根分區新位置 /dev/sdb10 918056960 934834175 8388608 83 Linux /dev/sdb11 934836224 951613439 8388608 83 Linux /dev/sdb12 951615488 960004095 4194304 82 Linux swap / Solaris /dev/sdb13 960004159 970502711 5249276+ 83 Linux
在 Ubuntu 下執行 update-grub,輸出顯示三個作業系統均被偵測到:
Generating grub configuration file ... Found background image: ubuntu_kylin_grub_bg.tga Found linux image: /boot/vmlinuz-3.13.0-46-generic Found initrd image: /boot/initrd.img-3.13.0-46-generic Found linux image: /boot/vmlinuz-3.13.0-32-generic Found initrd image: /boot/initrd.img-3.13.0-32-generic Found memtest86+ image: /boot/memtest86+.elf Found memtest86+ image: /boot/memtest86+.bin Found Windows 7 (loader) on /dev/sda1 Found CentOS release 6.6 (Final) on /dev/sdb9 done
重啟後 CentOS 仍無法啟動,說明問題不在 GRUB 選單生成,而在啟動參數傳遞。
懷疑 CentOS 啟動時自動掛載 /home 和 /var 獨立分區失敗,遂修改 CentOS 的 /etc/fstab,將所有分區標識從裝置名(如 /dev/sdb9)改為 UUID。查看 UUID 對應關係可用:
ls -l /dev/disk/by-uuid/
修改後重啟,問題依舊。
檢視 /boot/grub/grub.cfg 中 CentOS 的啟動條目,發現關鍵問題在第 9 行 linux 命令的 root= 參數:
menuentry 'CentOS release 6.6 (Final) (on /dev/sdb9)' --class gnu-linux --class gnu --class os $menuentry_id_option 'osprober-gnulinux-simple-d24c3228-5ffc-4937-8411-a69681c3b54e' {
insmod part_msdos
insmod ext2
set root='hd1,msdos9'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd1,msdos9 --hint-efi=hd1,msdos9 --hint-baremetal=ahci1,msdos9 d24c3228-5ffc-4937-8411-a69681c3b54e
else
search --no-floppy --fs-uuid --set=root d24c3228-5ffc-4937-8411-a69681c3b54e
fi
linux /boot/vmlinuz-2.6.32-504.12.2.el6.i686 ro root=/dev/sdb8 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=128M KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet vga=791
initrd /boot/initramfs-2.6.32-504.12.2.el6.i686.img
}
錯誤點:root=/dev/sdb8 指向舊分區,實際上 sdb8 現為 NTFS 分區,導致內核無法識別檔案系統類型。手動改為 root=/dev/sdb9 即可正常啟動。
執行 update-grub 後配置又被覆蓋。分析發現,CentOS 的啟動條目由 /etc/grub.d/30_os-prober 生成,而 linux-boot-prober 透過讀取 CentOS 分區中的 menu.lst(GRUB Legacy 配置)來提取啟動參數。檢視 CentOS /boot/grub/menu.lst:
title CentOS (2.6.32-504.12.2.el6.i686) root (hd0,9) kernel /boot/vmlinuz-2.6.32-504.12.2.el6.i686 ro root=/dev/sdb8 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=128M KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet vga=791 initrd /boot/initramfs-2.6.32-504.12.2.el6.i686.img
第 2 行 root (hd0,9) 已修正(對應 sdb9),但第 3 行 root=/dev/sdb8 未同步更新,導致 os-prober 提取錯誤參數。
修正 CentOS menu.lst 中 kernel 行的 root= 參數為 /dev/sdb9,再次執行 update-grub,CentOS 終於能正常啟動。
os-prober 會讀取其他作業系統的引導配置,需確保各系統內部配置一致