前置知識:你必須知道grub的啓動過程以及bios和uefi的相關基礎知識,能夠參考:《Unified Extensible Firmware Interface Wikipedia》、《linux啓動過程簡介》html
先說說三個變量是幹嗎的:node
當前被加載的"core.img"(bios的core.img,uefi的BOOTX64.EFI或grubx64.efi等鏡像)所在目錄的絕對路徑。例如:UEFI啓動多是'(hd0,gpt1)/EFI/GRUB或'(cd0)/EFI/BOOT',BIOS啓動多是'(hd0)'linux
這個變量是指GRUB2的安裝目錄,即絕對路徑形式的'/boot/grub'目錄位置,如例如'(hd0,gpt1)/grub'或'(hd0,msdos2)/boot/grub'。初始值由GRUB在啓動時根據"grub-install"在安裝時提供的信息自動設置,這些信息是由grub-install腳本直接寫入到grub鏡像(bios的core.img,uefi的BOOTX64.EFI或grubx64.efi等鏡像)的,固然,也能夠在grub的rescue模式下用grub的命令直接修改,如:set prefix=(hd1,gpt2)/grub。ios
GRUB2的安裝目錄中存在着這麼幾個文件夾和文件git
文件夾:github
fonts:存在着一些字體shell
locale:區域化相關ubuntu
x86_64-efi:模塊的二進制文件,以.mod爲後綴。你insmod所操做的模塊,都在這裏面有,好比ext4.mod、fat.mod這些文件系統模塊,gzio等解壓支持的模塊。windows
themes:一些主題,就是你grub界面的背景啥的。centos
文件:
grub.cfg:這是grub的啓動shell腳本,對於用戶來講,是最重要的文件,幾乎是用戶配置grub的惟一的配置文件。經過這個文件用戶能夠控制grub加載操做系統的行爲,好比添加一個menuentry就是添加一個操做系統啓動選項,每一個選項中能夠指定操做系統內核盡享和initramfs鏡像等等。下面是一個grub.cfg的實例:
1 #因爲"$prefix"的值是在"grub-install"安裝時肯定的,而且嵌入'core.img'中的模塊也是隨硬件變化的, 2 #因此不要只是簡單的複製'grub'目錄處處使用,而應該在每個介質上都使用"grub-install"進行安裝。 3 ############################################################################### 4 #(1)本配置文件要求"grub"目錄所在分區的卷標必須是"GRUB2"。 5 #(2)爲了保持最大程度的BIOS兼容性,"GRUB2"分區必須位於磁盤的前 137GB 範圍。 6 ############################################################################### 7 # 若是要在windows上安裝GRUB2的話,必須首先以管理員身份打開命令提示符,而後運行 8 # wmic diskdrive list brief 9 # 命令查看安裝目標,最後再使用例以下面這樣的命令進行安裝: 10 # grub-install.exe --boot-directory=g: --recheck --target=x86_64-efi --efi-directory=g: --no-nvram --removable \\.\PHYSICALDRIVE5 11 # grub-install.exe --boot-directory=g: --recheck --target=i386-pc \\.\PHYSICALDRIVE5 12 ############################################################################### 13 14 ################# 15 ## (1)特殊變量 ## 16 ################# 17 #禁止驗證簽名 18 set check_signatures=no 19 #默認啓動第一個菜單項 20 set default=0 21 #若是第一個菜單項啓動失敗,轉而啓動第二個菜單項 22 set fallback=1 23 #優先使用最常規的1024x768分辨率,以保證在不一樣的屏幕上擁有一致的菜單效果,若是失敗再自動匹配分辨率 24 set gfxmode=1024x768,auto 25 #使用本身製做的24px的大號字體以免默認字體過小看不清 26 set gfxterm_font=WenQuanYiMicroHeiMono24px 27 #將GRUB2設置爲簡體中文界面 28 set lang=zh_CN 29 #指定翻譯文件(*.mo)的目錄,若未明確設置此目錄,則沒法顯示中文界面。 30 set locale_dir=$prefix/locale 31 #每一滿屏後暫停輸出,以避免信息太多一閃而過看不清 32 set pager=1 33 #開啓密碼驗證功能,並設置一個名爲'root'的超級用戶 34 set superusers=root 35 #設置菜單的超時時間爲5秒 36 set timeout=5 37 38 ################# 39 ## (2)公共模塊 ## 40 ################# 41 #兩種最流行的磁盤分區格式(partmap.lst) 42 insmod part_gpt 43 insmod part_msdos 44 #常見文件系統驅動(fs.lst) 45 insmod fat 46 insmod exfat 47 insmod ntfs 48 insmod iso9660 49 insmod ext2 50 insmod xfs 51 #一次性加載全部可用的視頻驅動 52 insmod all_video 53 #圖形模式終端 54 insmod gfxterm 55 #背景圖片支持 56 insmod png 57 58 ######################################### 59 ## (3)公共命令(必須放在模塊和變量以後) ## 60 ######################################### 61 #激活圖形模式的輸出終端,以容許使用中文和背景圖 62 terminal_output gfxterm 63 #設置背景圖片 64 background_image $prefix/themes/1024x768.png 65 #加載本身製做的24px的大號字體文件($prefix/fonts/WenQuanYiMicroHeiMono24px.pf2) 66 loadfont WenQuanYiMicroHeiMono24px 67 #設置'root'用戶的哈希密碼[經過"grub-mkpasswd-pbkdf2"工具生成] 68 password_pbkdf2 root grub.pbkdf2.sha512.69.7DBCA469F80EA1C0A8A1E2FEBC4F8463.B073C1C89EC1E85309C3D6A1BAFF4356 69 70 ################# 71 ## (4)菜單項 ## 72 ################# 73 74 menuentry '正常啓動(Windows)' --unrestricted { 75 if [ 'pc' == $grub_platform ] ; then 76 if search --file --set /bootmgr ; then 77 chainloader +1 78 elif search --file --set /ntldr ; then 79 chainloader +1 80 fi 81 elif [ 'efi' == $grub_platform ] ; then 82 if search --file --set /EFI/Microsoft/Boot/bootmgfw.efi ; then 83 chainloader /EFI/Microsoft/Boot/bootmgfw.efi 84 fi 85 fi 86 } 87 88 #http://www.wepe.com.cn/download.html 89 menuentry '系統救援(WinPE)' --users=root { 90 if [ 'pc' == $grub_platform -a -f $prefix/winpe/memdisk ] ; then 91 if [ -f $prefix/winpe/WinPE.iso ] ; then 92 linux16 $prefix/winpe/memdisk iso raw 93 initrd16 $prefix/winpe/WinPE.iso 94 fi 95 elif [ 'efi' == $grub_platform -a -f $prefix/winpe/bootmgfw.efi -a -f $prefix/winpe/BCD ] ; then 96 if [ -f $prefix/winpe/WinPE.wim -a -f $prefix/winpe/boot.sdi ] ; then 97 chainloader $prefix/winpe/bootmgfw.efi 98 fi 99 fi 100 } 101 102 #https://mirrors.tuna.tsinghua.edu.cn/archlinux/iso/latest/ 103 if [ -f $prefix/linux/archlinux.iso ] ; then 104 menuentry 'Arch Linux LiveCD [root/空]' --unrestricted { 105 loopback loop0 $prefix/linux/archlinux.iso 106 linux (loop0)/arch/boot/x86_64/vmlinuz img_label=GRUB2 img_loop=/grub/linux/archlinux.iso systemd.wants=sshd.service 107 initrd (loop0)/arch/boot/x86_64/archiso.img 108 } 109 fi 110 111 #https://mirrors.163.com/gentoo/releases/amd64/autobuilds/current-install-amd64-minimal/ 112 #由於Gentoo官方的最小安裝CD不支持UEFI啓動,因此不可用於在UEFI環境中安裝Gentoo 113 if [ -f $prefix/linux/install-amd64-minimal.iso ] ; then 114 menuentry 'Mini Gentoo LiveCD [root/123]' --unrestricted { 115 loopback loop0 $prefix/linux/install-amd64-minimal.iso 116 linux (loop0)/isolinux/gentoo cdroot isoboot=/grub/linux/install-amd64-minimal.iso dosshd nokeymap passwd=123 117 initrd (loop0)/isolinux/gentoo.igz 118 } 119 fi 120 121 #https://mirror.umd.edu/calculate/release/ 122 #https://www.calculate-linux.org/main/en/download 123 # Calculate Linux Scratch 是基於Gentoo製做的 LiveCD , 124 #包含編譯工具(GCC,Binutils,...)、支持UEFI、支持WiFi, 125 #既可用做LFS(Linux From Scratch)的宿主系統、也可用於在UEFI環境中安裝 Gentoo 126 if [ -f $prefix/linux/cls.iso ] ; then 127 menuentry 'Live GCC x64 [root/root]' --unrestricted { 128 loopback loop0 $prefix/linux/cls.iso 129 linux (loop0)/boot/vmlinuz root=live iso-scan/filename=/grub/linux/cls.iso vga=current nodevfs noresume nodmraid 130 initrd (loop0)/boot/initrd 131 } 132 fi 133 134 #https://mirrors.huaweicloud.com/centos/7/isos/x86_64/ 135 if [ -f $prefix/linux/CentOS-LiveGNOME.iso ] ; then 136 menuentry 'CentOS 7.6 GNOME LiveCD [root/空](可退出liveuser後再用root登陸)' --unrestricted { 137 loopback loop0 $prefix/linux/CentOS-LiveGNOME.iso 138 linux (loop0)/isolinux/vmlinuz0 rd.live.image root=live:CDLABEL=CentOS-7-x86_64-LiveGNOME-1810 iso-scan/filename=/grub/linux/CentOS-LiveGNOME.iso systemd.wants=sshd.service inst.lang=zh_CN 139 initrd (loop0)/isolinux/initrd0.img 140 } 141 fi 142 143 #https://mirrors.ustc.edu.cn/debian-cd/current-live/amd64/iso-hybrid/ 144 #也適用於'Kali LiveCD [root/toor]' https://cdimage.kali.org/current/ 145 if [ -f $prefix/linux/debian-live-kde.iso ] ; then 146 menuentry 'Debian 9.6 KDE LiveCD (NO SSH)' --unrestricted { 147 loopback loop0 $prefix/linux/debian-live-kde.iso 148 linux (loop0)/live/vmlinuz-4.9.0-8-amd64 boot=live findiso=/grub/linux/debian-live-kde.iso components username=root locales=zh_CN.UTF-8 149 initrd (loop0)/live/initrd.img-4.9.0-8-amd64 150 } 151 fi 152 153 #https://mirrors.aliyun.com/fedora/releases/29/Spins/x86_64/iso/ 154 #只有 Xfce LiveCD 能夠設置中文界面 155 if [ -f $prefix/linux/Fedora-Xfce-Live.iso ] ; then 156 menuentry 'Fedora 29 Xfce LiveCD [root/空](可退出liveuser後再用root登陸)' --unrestricted { 157 loopback loop0 $prefix/linux/Fedora-Xfce-Live.iso 158 linux (loop0)/isolinux/vmlinuz rd.live.image root=live:CDLABEL=Fedora-Xfce-Live-29-20181029-1 iso-scan/filename=/grub/linux/Fedora-Xfce-Live.iso systemd.wants=sshd.service locale.LANG=zh_CN.utf8 inst.lang=zh_CN 159 initrd (loop0)/isolinux/initrd.img 160 } 161 fi 162 163 #https://ftp.sjtu.edu.cn/opensuse/distribution/openSUSE-stable/live/ 164 if [ -f $prefix/linux/openSUSE-Leap-KDE-Live.iso ] ; then 165 menuentry 'openSUSE Leap 15.0 KDE LiveCD [root/空]' --unrestricted { 166 loopback loop0 $prefix/linux/openSUSE-Leap-KDE-Live.iso 167 linux (loop0)/boot/x86_64/loader/linux root=live:CDLABEL=openSUSE_Leap_15.0_KDE_Live iso-scan/filename=/grub/linux/openSUSE-Leap-KDE-Live.iso systemd.wants=sshd.service lang=zh_CN 168 initrd (loop0)/boot/x86_64/loader/initrd 169 } 170 fi 171 172 #https://mirrors.shu.edu.cn/ubuntu-cdimage/lubuntu/releases/ 173 #也適用於 KDE neon LiveCD https://files.kde.org/neon/images/neon-userltsedition/current/neon-userltsedition-current.iso 174 if [ -f $prefix/linux/lubuntu.iso ] ; then 175 menuentry 'Ubuntu LXQt LiveCD (NO SSH)' --unrestricted { 176 loopback loop0 $prefix/linux/lubuntu.iso 177 linux (loop0)/casper/vmlinuz boot=casper iso-scan/filename=/grub/linux/lubuntu.iso username=root locale=zh_CN keyboard-configuration/layoutcode=us 178 initrd (loop0)/casper/initrd 179 } 180 fi 181 182 menuentry '關機' --unrestricted { halt ; } 183 menuentry '從新啓動' --unrestricted { reboot ; } 184 185 #https://rhinstaller.github.io/anaconda/boot-options.html 186 #硬盤安裝通用於全部包含"Packages"目錄的 CentOS/Fedora ISO映像(Minimal,DVD,Everything) 187 #網絡安裝通用於全部包含"images"目錄的 CentOS/Fedora ISO映像(Minimal,DVD,Everything,NetInstall) 188 #https://mirrors.zju.edu.cn/centos/7/isos/x86_64/ 189 if [ -f $prefix/linux/CentOS-Minimal.iso ] ; then 190 menuentry '硬盤安裝 CentOS [最小安裝]' --unrestricted { 191 loopback loop0 $prefix/linux/CentOS-Minimal.iso 192 linux (loop0)/isolinux/vmlinuz inst.repo=hd:LABEL=GRUB2:/grub/linux/CentOS-Minimal.iso inst.lang=zh_CN 193 initrd (loop0)/isolinux/initrd.img 194 } 195 menuentry '網絡安裝 CentOS 7.x [不支持WiFi]' --unrestricted { 196 loopback loop0 $prefix/linux/CentOS-Minimal.iso 197 linux (loop0)/images/pxeboot/vmlinuz inst.repo=https://mirrors.aliyun.com/centos/7/os/x86_64/ inst.lang=zh_CN ip=dhcp nameserver=223.6.6.6 198 initrd (loop0)/images/pxeboot/initrd.img 199 } 200 fi 201 202 #https://www.debian.org/releases/stable/amd64/ch05s03.html.zh-cn 203 #https://www.debian.org/releases/stable/amd64/ch06s03.html.zh-cn 204 #最好將用於硬盤安裝的ISO映像放在文件系統的根目錄或第一層子目錄中(可簡化ISO映像的搜索) 205 #https://mirrors.163.com/debian/dists/stable/main/installer-amd64/current/images/hd-media/ 206 #https://mirrors.163.com/ubuntu/dists/bionic/main/installer-amd64/current/images/hd-media/ 207 #硬盤安裝也適用於 Alternative Ubuntu Server ISO [ http://cdimage.ubuntu.com/releases/18.04/release/ubuntu-18.04.1-server-amd64.iso ] 208 if [ -f $prefix/linux/debian/vmlinuz -a -f $prefix/linux/debian/initrd.gz ] ; then 209 menuentry '硬盤安裝 Debian [自動搜索ISO映像(最好放在根目錄)]' --unrestricted { 210 linux $prefix/linux/debian/vmlinuz priority=low vga=791 locale=zh_CN 211 initrd $prefix/linux/debian/initrd.gz 212 } 213 fi 214 #https://mirrors.163.com/debian/dists/stable/main/installer-amd64/current/images/netboot/ 215 #https://mirrors.163.com/ubuntu/dists/bionic/main/installer-amd64/current/images/netboot/ 216 #網絡安裝也適用於 Ubuntu 的 mini.iso 映像(支持WiFi網絡) 217 if [ -f $prefix/linux/debian/mini.iso ] ; then 218 menuentry '網絡安裝 Debian [不支持WiFi]' --unrestricted { 219 loopback loop0 $prefix/linux/debian/mini.iso 220 linux (loop0)/linux priority=low vga=791 locale=zh_CN 221 initrd (loop0)/initrd.gz 222 } 223 fi 224 225 #https://doc.opensuse.org/documentation/leap/startup/html/book.opensuse.startup/cha.boot_parameters.html 226 #https://ftp.sjtu.edu.cn/opensuse/distribution/openSUSE-stable/iso/ 227 if [ -f $prefix/linux/openSUSE-Leap-DVD.iso ] ; then 228 menuentry '硬盤安裝 openSUSE Leap' --unrestricted { 229 loopback loop0 $prefix/linux/openSUSE-Leap-DVD.iso 230 linux (loop0)/boot/x86_64/loader/linux install=hd:/grub/linux/openSUSE-Leap-DVD.iso lang=zh_CN 231 initrd (loop0)/boot/x86_64/loader/initrd 232 } 233 fi 234 #https://mirrors.nju.edu.cn/opensuse/distribution/openSUSE-stable/iso/ 235 if [ -f $prefix/linux/openSUSE-Leap-NET.iso ] ; then 236 menuentry '網絡安裝 openSUSE Leap [支持WiFi]' --unrestricted { 237 loopback loop0 $prefix/linux/openSUSE-Leap-NET.iso 238 linux (loop0)/boot/x86_64/loader/linux install=https://mirrors.aliyun.com/opensuse/distribution/openSUSE-stable/repo/oss/ lang=zh_CN netsetup=dhcp nameserver=223.6.6.6 239 initrd (loop0)/boot/x86_64/loader/initrd 240 } 241 fi
不過,grub.cfg通常都不會手動編輯的,而是用過grub-mkconfig -o /boot/grub/grub.cfg去生成。
grubenv:預設的一些環境變量能夠放到這,是一個文本文件
root變量通常在grub.cfg執行的過程當中設定的,指定了後續腳本中全部文件的其實位置,好比root=(hd0,gpt3),那麼/boot/xxx.img 就是在第一塊硬盤的第三個分區的boot目錄下,若是boot是單獨的分區,好比是第2塊硬盤的第2個分區,那麼就是 set root=(hd1,gpt2); linux vmlinuz-linux; 這兩行代碼來啓動一個linux內核了。
1.grub是如何肯定鏡像的安裝位置的?
若是是bios/mbr啓動,那麼鏡像的安裝位置是固定的,boot.img在mbr上,core.img在post-MBR gap上。你只須要在安裝時指定哪一個盤就能夠了,好比:
grub-install /dev/sda,
它就會安裝到第一塊盤上。
若是是bios/gpt方式,那麼必需要分一個bootable partition(或者叫bios boot,不一樣分區工具,叫法不同),這個分區不要格式化任何文件格式,留着就行了,通常1-2M大就能夠,鏡像就安裝在上面。
若是是uefi/gpt方式,那麼必需要有一個efi system partition(叫作esp)的專門分區,分區格式是esp,文件系統是flat32。在安裝的時候,先把這個分區掛載上,而後用--efi-directory指定一下他的位置,若是它是掛載到/boot/efi上,那麼不用指定,grub-install會默認esp在那。uefi安裝的示例以下:
# grub-install --target=x86_64-efi --efi-directory=esp --bootloader-id=GRUB
--target指定了系統架構,--bootloader-id指定了grub的efi啓動點的名字,到時候你能夠在主板設置上看到它。
至於uefi/mbr方式,那種太奇怪了,你不會碰到的。
2.grub-install是在安裝grub時,是如何肯定prefix的?
你在哪一個操做系統上運行它,這個操做系統的/boot/grub所對應的路徑就是prefix。好比你的操做系統的boot分區在第1塊盤的第3個分區上,那麼prefix就是(hd0,gpt3)/grub。這就是網上常常說的默默操做系統去引導啥,好比說Ubuntu系統引導windows,其實就是說啓動點是grub,prefix是Ubuntu的/boot/grub。
說句題外話,一個操做系統是不可能引導另外一個操做系統的,只有引導器(BootLoader)如grub才能引導操做系統啓動,或者uefi能夠直接引導操做系統啓動。而且,grub還不能直接應道dos(windows)啓動,而是先引導windows系統的引導器(如EasyBCD),再讓這個引導器去引導windows,這種方式成爲鏈式引導(chainload),好比:
menuentry 'Windows'{ insmod part_msdos insmod ntfs set root='(hd0,msdos1)' chainloader +1 }
3.是否是必定要掛載esp分區?
若是你肯定不會在去動grub了,那麼能夠不掛載,efi分區只在你操做引導器的時候纔有用,日常它是沒有用的。因此看到有些教程說把它掛載到/efi上,有的則是/boot/efi上,甚至有的直接說掛到/boot上這樣方便直接啓動。其實均可以,掛載到不一樣位置,隻影響你grub-install的操做結果,操做事後,他就沒用了。
4.linux內核是如何肯定文件掛載樹的?我能不能把/etc也搞到一個單獨的分區上?
有人會說有/etc/fstab,對,沒錯,可是,內核啓動的時候,它首先得知道/etc在那個盤對吧?否則它怎麼知道到fstab呀。看來這就是個先有雞仍是先有蛋的問題,怎麼解決呢?
若是你仔細看上面的grub.cfg,你就會發現,在啓動Linux內核的語句中有許多參數,好比這句: linux (loop0)/boot/x86_64/loader/linux root=live:CDLABEL=openSUSE_Leap_15.0_KDE_Live iso-scan/filename=/grub/linux/openSUSE-Leap-KDE-Live.iso systemd.wants=sshd.service lang=zh_CN ,有一個root=xxx,這就是指定了root參數,因此就能知道/在哪,也就知道了/etc在哪。因此,通常來講你的/etc是不能掛載到單獨的盤的,除非你本身編譯一下內核,加入一個etc=xxx以內的參數,在運行linux命令的適合指定這個etc的盤,這樣你就能夠把etc單獨搞到別的盤了,但通常沒有人有這麼蛋疼的需求。若是你必定要這麼作,能夠參考一下這個老哥《Moving /etc to separate partition》。