grub2_grub2安装 - CSDN
精华内容
参与话题
  • GRUB2配置

    千次阅读 2019-03-01 14:52:45
    GRUB 2 通过运行/etc/grub.d/folder目录下的脚本来 建立配置文件 (grub.cfg) ,并且/etc/default/grub这个文件也可以配置。update-grub命令(手动运行,或更新内核的时候会被执行)可以自动更新grub.cfg ...

    原文:https://blog.csdn.net/duanlove/article/details/8066570

    介绍 

    GRUB 2 通过运行/etc/grub.d/folder  目录下的脚本来 建立配置文件 (grub.cfg) ,并且/etc/default/grub这个文件也可以配置。update-grub命令(手动运行,或更新内核的时候会被执行)  可以自动更新grub.cfg .这个命令会激活上面的脚本,并且会寻找系统中存在的操作系统和内核。一旦发现操作系统或内核,那么它们会被加入到 GRUB 2 的启动菜单当中。 

    通过以下两个命令中的任意一个 可以知道,GRUB2被安装在了哪个分区:

    Device: sudo grub-probe -t device /boot/grub

    UUID: sudo grub-probe -t fs_uuid /boot/grub

    例如: 

    $ grub-probe -t device /boot/grub/
    /dev/sda1
    $ sudo grub-probe -t fs_uuid /boot/grub/
    efa0f8fd-d69d-4931-8275-d25f8871511d
    $ sudo grub-probe -t device /boot/grub/
    /dev/sda1
    $
    $ df -h
    文件系统            容量  已用  可用 已用%% 挂载点
    /dev/sda5              19G   16G  2.3G  87% /
    none                  1.5G  672K  1.5G   1% /dev
    none                  1.5G  104K  1.5G   1% /dev/shm
    none                  1.5G  356K  1.5G   1% /var/run
    none                  1.5G     0  1.5G   0% /var/lock
    /dev/sda1             3.7G  132M  3.4G   4% /boot     # 我这台机的 grub2是装在 /boot 分区的
    /dev/sda8             426G  303G  102G  75% /home
    /dev/sda7             5.6G  417M  4.9G   8% /opt
    df: "/home/swtd1/.gvfs": 无效的跨设备连接
    /home                 426G  303G  102G  75% /home

     

    安装 在 sda1 的操作系统接管 grub2。

    主目录和文件 -- Main Directories & Files

    The Menu: /boot/grub/grub.cfg

    grub.cfg 这个文件,在以前的grub版本( GRUB 0.97')是 menu.lst    。grub.cfg这个文件不像 menu.list这个文件, menu.list是直接编辑的。

    而grub.cfg是用命令(每个命令负责这个配置文件中的某一块的更新)来更新的。

    grub.cfg 通过运行update-grub    来更新的。update-grub 其实就跟如下命令是一个作用。

          grub-mkconfig -o /boot/grub/grub.cfg.

    如果用户希望在一个不同的位置创建一个不同名字的启动菜单的话,就需要通过 “-o” 选项来指定新的路径。

     

    当 grub-install  命令运行的时候,并不创建或者更新 grub.cfg 文件。

     

    直接修改 grub.cfg  --- Editing grub.cfg directly

    手动修改 grub.cfg 需要注意:

    如果其他的任务会运行 update-grub ,那么应该在 update-grub 运行之后, 再编辑 grub.cfg  。也就是说在编辑grub.cfg之前,应该所有需要的内核和相关资源已经有了。

    当然,你手动编辑的内容,一般来说在下次运行update-grub  之后,都会被覆盖掉。update-grub 是根据它自己的规则来更新grub.cfg。

     grub.cfg的部分内容 是/etc/grub.d     下的脚本生成的。用户可以根据需要编辑这个目录下的脚本。

     

     

    用户设置: /etc/default/grub

    /etc/default/grub 文件包含了很多默认配置。

     /usr/sbin$ ls grub-*
    grub-install   grub-mkdevicemap  grub-probe   grub-set-default
    grub-mkconfig  grub-mknetdir     grub-reboot  grub-setup

     在 /usr/sbin 目录下,以 grub- 开头的文件都是 脚本文件,并非二进制可执行文件。

    很多预定义的变量包含在/usr/sbin/grub-mkconfig    这个文件中,用如下命令可以列出这些预定义的变量:

     

    grep "export GRUB_DEFAULT" -A50 /usr/sbin/grub-mkconfig | grep GRUB_

     

    /usr/sbin$ grep "export GRUB_DEFAULT" -A50 /usr/sbin/grub-mkconfig | grep GRUB_
    export GRUB_DEFAULT \
      GRUB_HIDDEN_TIMEOUT \
      GRUB_HIDDEN_TIMEOUT_QUIET \
      GRUB_TIMEOUT \
      GRUB_DEFAULT_BUTTON \
      GRUB_HIDDEN_TIMEOUT_BUTTON \
      GRUB_TIMEOUT_BUTTON \
      GRUB_BUTTON_CMOS_ADDRESS \
      GRUB_BUTTON_CMOS_CLEAN \
      GRUB_DISTRIBUTOR \
      GRUB_CMDLINE_LINUX \
      GRUB_CMDLINE_LINUX_DEFAULT \
      GRUB_CMDLINE_XEN \
      GRUB_CMDLINE_XEN_DEFAULT \
      GRUB_CMDLINE_NETBSD \
      GRUB_CMDLINE_NETBSD_DEFAULT \
      GRUB_TERMINAL_INPUT \
      GRUB_TERMINAL_OUTPUT \
      GRUB_SERIAL_COMMAND \
      GRUB_DISABLE_LINUX_UUID \
      GRUB_DISABLE_RECOVERY \
      GRUB_VIDEO_BACKEND \
      GRUB_GFXMODE \
      GRUB_BACKGROUND \
      GRUB_THEME \
      GRUB_GFXPAYLOAD_LINUX \
      GRUB_DISABLE_OS_PROBER \
      GRUB_INIT_TUNE \
      GRUB_SAVEDEFAULT \
      GRUB_BADRAM

     

    脚本: /etc/grub.d/

     

    $ ls /etc/grub.d/
    00_header        10_linux      20_memtest86+  40_custom  README
    05_debian_theme  20_linux_xen  30_os-prober   41_custom

     在 /etc/grub.d/ 目录下的脚本,当 update-grub执行的时候,会被读取,并合并到 /boot/grub/grub.cfg   这个文件中。

    grub.cfg文件中的 菜单条目的放置,是由 /etc/grub.d/   目录下的脚本运行的顺序来决定的。文件名以数字开头的的脚本会被先执行,并且数字小的先执行。比如10_linux 在20_memtest之前执行。而20_memtest   会在40_custom  之前执行。文件名以字母开头的(alphabetic)的脚本在数字命名的脚本之后运行。

     自定义的 启动菜单入口(menu entries)可以被添加到40_custom   这个文件中,或者单独创建一个文件。40_custom  中的菜单入口将会出现在启动菜单的最底部。一个以“06_”开头的自定义文件,将出现在 启动菜单的最顶部。

     

     update-grub执行的时候,  /etc/grub.d/ 下的脚本会被执行。

    脚本描述:

    00_header

    设置环境变量,比如 系统文件位置、video设置和之前保存的入口(previously saved entries) 。这个也导入了一些相关的东西(存储在/etc/default/grub)。用户通常不需要改变这个文件。

     

    05_debian_theme

    这个文件的主要目的是设置GRUB2的背景图片,文本颜色,选择高亮和主题。这些文件初始化菜单显示。关于如何设置字体和显示等请参考:Grub2/Displays  (https://help.ubuntu.com/community/Grub2/Displays)

     

    10_linux

    识别在 root device中操作系统正在使用的内核,并且为这些内核创建(menu entries) . 这个包含了相应的“recovery mode (恢复模式)”选项。在GRUB 1.99和之后的版本中, 在 启动主菜单页面,仅显示最新的内核。其他的内核被包含在了子启动菜单中( submenu)。 更多submenu相关信息请参考Grub2/Submenus  。

    Note:对于早期的GRUB 2版本, 所有位于 boot目录的内核都包含在 main menu 中. 如果要减少显示的内核,那就要删除/boot文件夹下的旧内核,或者使用一个有效的的grub2自定义应用。

    20_memtest86+

    寻找 /boot/memtest86+.bin ,并且把它作为一个选项加入到 GRUB 2 启动菜单(boot menu)当中。当前没有任何方式可以从这个启动菜单当中去除这个“memtest86+”的入口。但是,可以通过去掉文件可执行权限,并运行update-grub的方式来禁止ofmemtest86+ 的显示:

     sudo chmod -x /etc/grub.d/20_memtest86+
    sudo update-grub
     

    30_os-prober

    这个脚本使用“os-prober” 去搜索linux和其他操作系统,并且把结果放置到GRUB 2 的菜单中。

    这个文件包含如 Windows, Linux, OSX, 和 Hurd 这些操作系统的选项。
    在这个文件中的一些变量,决定了 在/boot/grub/grub.cfg  文件中 和 GRUB 2 menu 中 最终被显示的某系名字的格式(format of the displayed names)。 熟悉基本脚本的用户可以改变这些变量,以达到改变 GRUB2菜单入口格式 的目的。

    The user can insert an entry into /etc/default/grub which disables this script (seeConfiguring GRUB 2). Removing the executable bit from the file will also prevent it from searching for other operating systems.

    By default os-prober ignores any disks that possess "dmraid" signatures, which can be listed via sudo dmraid -r -c (if installed).

    If the script finds another Ubuntu/Linux operating system, it will attempt to use the titles contained in the10_linux section of that installation'sgrub.cfg file. If not found, the script will construct a menuentry from the actual boot information it locates.

    40_custom 

    这个文件是一个添加自定义启动菜单入口的模板。当执行 update-grub的时候,这个文件的内容会被加入到grub.cfg总。

    The contents of this file, below the "exec tail -n +3 $0" line and the default comments, are imported directly into/boot/grub/grub.cfg without any changes.

    As the comments at the top of the file state, add custom lines below those already contained in the40_custom file.

    The file can be renamed or copied. The file must be executable to be incorporated into the GRUB 2 menu.
    As mentioned in the introduction of this section, the name of the file determines the location of its contents in the GRUB 2 menu. As a general rule, if using numerals at the start it is advisable to allow the00_header and05_debian_theme scripts to be run before the first custom menu. These files contain no menuentries and thus will not interfere with a menuentry from a custom script with a lower priority.

    Configuring GRUB 2

    Configuration changes are normally made to /etc/default/grub and to the custom files located in/etc/grub.d. Any changes made directly to the/boot/grub/grub.cfg are overwritten wheneverupdate-grub is executed either by the user or when called automatically by various system functions.

    After editing /etc/default/grub or the scripts in the/etc/grub.d folder the user should runsudo update-grub to incorporate the changes into the GRUB 2 menu.

     Some of the most common changes, such as the default OS/kernel and menu timeout, can be changed from within a GUI applications such as Grub Customizer.

    /etc/default/grub

    This file contains basic settings which would be considered normal for the user to configure. Options include the time the menu is displayed, the default OS to boot, etc. The default options included in file upon installation are only a small number of the variables which GRUB 2 can recognize. The GRUB 2 defined variables can be identified using the command previously documented in theGRUB 2 Settings section or at the end of this section.

    In addition to the defined variables, the user may introduce self-created variable(s) and use them in the scripts contained in the/etc/grub.d folder.

    Editing the File

    The grub file is a system file, therefore any editing must be done by a user with 'Administrator/root' privileges. The file is a simple text file and can be edited by any text editor. The default text editor in Ubuntu is Gedit, and the file can be edited with the following command. "gksu" is the graphical equivalent of "sudo" and the "&" allows the terminal to be used to update GRUB 2 once the user saves the file.

     gksu gedit /etc/default/grub &
    After making changes and saving the file, the GRUB 2 menu must be updated to include the changes by running:

     sudo update-grub
    Specific Entries

    This section details some of the entries available in the /etc/default/grub file. Much of this information can also be found by referring the theGnu GRUB manual or on the system itself by running the following command:

     info -f grub -n 'Simple configuration'
    GRUB_DEFAULT=

    Sets the default menu entry. Entries may be numeric, a complete menuentry quotation, or "saved"
    GRUB_DEFAULT=0 Sets the default menu entry by menu position. The first "menuentry" ingrub.cfg is 0, the second is 1, etc.

    Note: Grub 1.99 introduces a submenu menu structure. For a menu item in a submenu, the entry becomes a two-digit entry. The first entry is the position of thesubmenu title in the main menu. The second entry is the position within thesubmenu. If the submenu is the 3rd entry in the main entry, and the user wishes to boot the first entry in thesubmenu, it would be designated as "2>0".See the community documentation for a fuller explanation:Grub2/Submenus.

    GRUB_DEFAULT="xxxx" An exact menu entry, including the quotation symbols, may also be used. In this case, location in the menu will not matter.

    Example: GRUB_DEFAULT="Ubuntu, Linux 2.6.31-9-generic"

    Example (Submenu Entry): GRUB_DEFAULT="2>Ubuntu, Linux 2.6.38-8-generic"

    GRUB_DEFAULT=savedThe information in this section applies to GRUB 1.98 and later. The "saved" entry enables the "grub-reboot" and "grub-set-default" commands to set the default OS for future boots.

    The default OS for future boots will not be set merely by selecting an OS when booting.

    grub-set-default Sets the default boot entry until changed.

    The format is sudo grub-set-default X, withX being the menu entry position (starting with 0 as the first entry) or the exact menu string.

    Example: sudo grub-set-default 3

    Example: sudo grub-set-default "Ubuntu, Linux 2.6.32-15-generic"

    To obtain the existing menu entry choice number (starting from 0) or the menu entry "string", run:
    grep menuentry /boot/grub/grub.cfg

    grub-reboot This command sets the default boot entryfor the next boot only. The format of the command is the same as forgrub-set-default (see above).

    GRUB_SAVEDEFAULT=

    If set to true this setting will automatically set the last selected OS from the menu as the default OS on the next boot.

    No commands need be run to set the default OS.
    Any time a menu entry is manually selected from the GRUB 2 menu, it becomes the default OS.
    This option currently does not work if your /boot directory resides on an LVM partition or RAID.
    For this to work you must also set GRUB_DEFAULT=saved.

    Note: Ubuntu's version of Grub 1.99 introduced the submenu feature. Designating a default boot option located in thePrevious Linux versions submenu requires special formatting. For information regarding the submenu feature, please refer toGrub2/Submenus

    GRUB_HIDDEN_TIMEOUT=0

    Wait this many seconds for the user to press a key. During this period no menu is shown unless the user presses a key. If no key is pressed, control is passed to GRUB _TIMEOUT when the GRUB_HIDDEN_TIMEOUT expires. See the note regarding bugs to this feature at the end of this section.
    The developers envisioned using this setting with a GRUB_TIMEOUT value of 0. This would give users a period of time (GRUB_HIDDEN_TIMEOUT) to display the menu by pressing a key, after which the system would boot without the menu being displayed (GRUB_TIMEOUT=0).
    GRUB_HIDDEN_TIMEOUT=0

    No menu is displayed. The system is immediately booted to the default OS.
    This is the default setting with only one identified operating system.
    To display the menu under this condition, place a # symbol at the start of the line and ensure the GRUB_TIMEOUT setting is a positive integer.

    If the value is set to 0, a keystatus check is performed to determine if theSHIFT key is depressed. If GRUB 2 determines theSHIFT key is depressed during the boot process, the menu will be displayed. This gives the user a method of interrupting an automatic boot which would normally not display the menu.

    GRUB_HIDDEN_TIMEOUT=X

    X is a positive integer (e.g. 1, 5, 10, etc)

    The boot process will pause and display a blank screen or the designated splash image forX seconds. At the end of the time period, the system will boot. No menu will be displayed.

    While GRUB_HIDDEN_TIMEOUT is active, the menu can be displayed by pressing any key.
    GRUB_HIDDEN_TIMEOUT=

    No value entered after the = sign

    The menu will be displayed for the number of seconds designated by GRUB_TIMEOUT.
    GRUB_HIDDEN_TIMEOUT_QUIET=true

    Determines whether a countdown timer is displayed on a blank screen when using theGRUB_HIDDEN_TIMEOUT feature.

    true No countdown is displayed. The screen will be blank.

    false A counter will display on a blank screen for the duration of the GRUB_HIDDEN_TIMEOUT value.

    Note: There is a longstanding confirmed bug on the hidden menu feature in GRUB 1.97 to GRUB 1.99. The menu may not hide as specified in the description on this page. While editing the30_os-prober script can fix this issue, it is beyond the scope of this page.

    GRUB_TIMEOUT=10

    Sets the time period in seconds for the menu to be displayed before automatically booting unless the user intervenes.
    This instruction begins at the expiration of GRUB_HIDDEN_TIMEOUT.
    Setting this value to -1 will cause the menu to display until the user makes a selection.
    On a single OS system, by default this setting is not used and the menu will not display.
    To display the menu on each boot:
    Place a comment symbol (#) in front of the GRUB_HIDDEN_TIMEOUT entry

    Make the GRUB_TIMEOUT value 1 or higher.
    GRUB_DISTRIBUTOR=lsb_release -i -s 2> /dev/null || echo Debian

    Retrieves the descriptive name in the menu entry. (Ubuntu, Xubuntu, Debian, etc.)
    GRUB_CMDLINE_LINUX

    Entries on this line are added to the end of the 'linux' command line (GRUB legacy's "kernel" line) for both normal and recovery modes. It is used to pass options to the kernel.
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"

    This line imports any entries to the end of the 'linux' line (GRUB legacy's "kernel" line). The entries are appended to the end of the normal mode only.
    To view a black screen with boot processes displayed in text, remove "quiet splash".To see the grub splash image plus a condensed text output, use "splash".
    #GRUB_TERMINAL=console

    Uncomment to disable graphical terminal. This may provide help if the GRUB 2 menu is too large or unreadable. It also may help when using the GRUB_HIDDEN_TIMEOUT feature.
    #GRUB_DISABLE_LINUX_UUID="true"

    Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
    The search line will still use UUIDs. The linux line will use the/dev/sdXY convention when this option is enabled.

    #GRUB_GFXMODE=640x480

    GRUB 2 will automatically set the menu resolution to what it thinks is the best option. Uncommenting this line will set the resolution to 640x480, or you may change the value to another GRUB-compatible setting.
    The setting applies only to the boot menu display, not the resolution of the operating system that boots.
    Tip: Setting the same resolution in GRUB 2 and the operating system will decrease boot times slightly.
    Although not required, the user can also specify the color bit depth by appending it to the resolution setting. An example would be 1280x1024x24 or 640x480x32.
    The user can also add multiple resolutions. If GRUB 2 cannot use the first entry, it will try the next setting. Settings are separated by a comma. Example:1280x1024x16,800x600x24,640x480.

    If using a splash image, the resolution setting and the splash image size should be compatible for best results.
    If using an entry that produces a "not found" message when runningupdate-grub, try adding or changing the color bitdepth.

    Resolutions available to GRUB 2 can be displayed by typing vbeinfo in the GRUB 2 command line. The command line is accessed by typing "c" when the main GRUB 2 menu screen is displayed.

    If this line is commented (#) or the resolution is unavailable GRUB 2 uses the default setting determined by/etc/grub.d/00_header.

    In GRUB 1.99 (Natty) the 'optimum' resolution is selected by GRUB if no resolution is specified.
    #GRUB_DISABLE_LINUX_RECOVERY=true

    Allows the user to prevent the recovery options from inclusion on the GRUB 2 menu.
    Uncomment (remove the # symbol) to prevent the "Recovery" mode kernel options from appearing in the menu. If you want a "Recovery" option for only one kernel, make a special entry in /etc/grub/40_custom.
    GRUB_INIT_TUNE="480 440 1"

    Removing the comment symbol (#) allows GRUB 2 to play a single beep just prior to the Grub 2 menu display. More complex tunes can be designed by expanding the pitch/duration values.

    The format is tempo [pitch1 duration1] [pitch2 duration2] ...

    tempo is set once and applies to all duration settings.

    duration is the result of 60/tempo. A duration of 1 with atempo of 60 would produce a 1 second beep. Aduration of 1 with atempo of 480 produces a .125 second beep.

    Caution: The menu is displayed after the tune is complete. Creating a long tune will delay the appearance of the menu.
    Online documentation is available by typing info grub --index-search play in a terminal. It mentions the ability to play a tune with the commandplay file if the tune is composed with little-endian numbers.

    GRUB_BACKGROUND

    Sets the background image, enter the full path to the image here. See splash image configuration above for further details and other options.
    GRUB_DISABLE_OS_PROBER=true

    This entry is used to prevent GRUB from adding the results of os-prober to the menu. A value of "true" disables the os-prober check of other partitions for operating systems, including Windows, Linux, OSX and Hurd, during execution of theupdate-grub command. Using this option rather than removing the executable bit from the/etc/grub.d/30_os-prober file has several advantages:

    The setting can be easily changed while making other changes to thegrub file.

    While both methods prevent os-prober from running and placing items in the menu display, using this setting allows the30_os-prober script, but not theos-prober command, to run. This script enables the GRUB_HIDDEN_TIMEOUT setting and/or the ability to display a hidden menu by pressing the ESC key (depending on other settings). This functionality is lost if the30_os-prober script is disabled by making it unexecutable.

     To inspect the currenlty-available predesignated variables on your system's GRUB 2 library files, run:

    grep DEVICE -A40 /usr/sbin/grub-mkconfig

    User-Assigned Variables

     

    Variables in the /etc/default/grub file are read and acted upon as needed. This allows users to add their own variables in a central location and then alter the GRUB 2 scripts to meet their needs. Keeping the user-defined variables within this file allows easier management of, and change to, those variables when desired. To add a variable, use the following format:

    export <VARIABLE>

    The following example would define a variable used to omit a specific Ubuntu partition from the menu:
    Define and export the variable in /etc/default/grub :

    export GRUB_EXCLUDE_PARTITION="/dev/sda1"

    Establish the conditional in /etc/grub.d/30_os-prober in the10_linux section:

    if [ $GRUB_EXCLUDE_PARTITION = $LROOT ]; then

    or
    if [ ! $GRUB_EXCLUDE_PARTITION = $LROOT ]; then

    Complete the conditional at the appropriate point in the script
    Save the files and run sudo update-grub to incorporate the changes into the GRUB 2 menu.

     
    --------------------- 
    作者:duanlove 
    来源:CSDN 
    原文:https://blog.csdn.net/duanlove/article/details/8066570 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • 翻译了grub2官方手册的绝大部分内容,然后自己整理了一下。因为内容有点杂,所以章节安排上可能不是太合理,敬请谅解。 本人译作集合:http://www.cnblogs.com/f-ck-need-u/p/7048359.ht...

     

    本文原创地址在博客园:https://www.cnblogs.com/f-ck-need-u/archive/2017/06/29/7094693.html

     

    翻译了grub2官方手册的绝大部分内容,然后自己整理了一下。因为内容有点杂,所以章节安排上可能不是太合理,敬请谅解。

    本人译作集合:http://www.cnblogs.com/f-ck-need-u/p/7048359.html


    本文主要介绍的是grub2,在文末对传统grub进行了简述,但在grub2的内容部分中包含了很多grub2和传统grub的对比。

    如果仅仅是想知道grub2中的boot.img/core.img/diskboot.img/kernel.img或者传统grub中stage1/stage1_5/stage2文件的作用,请直接跳至相关内容处阅读。

    1.1 基础内容

    1.1.1 grub2和grub的区别

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/Changes-from-GRUB-Legacy.html#Changes-from-GRUB-Legacy

    只说明几个主要的:

    1.配置文件的名称改变了。在grub中,配置文件为grub.conf或menu.lst(grub.conf的一个软链接),在grub2中改名为grub.cfg。

    2.grub2增添了许多语法,更接近于脚本语言了,例如支持变量、条件判断、循环。

    3.grub2中,设备分区名称从1开始,而在grub中是从0开始的。

    4.grub2使用img文件,不再使用grub中的stage1、stage1.5和stage2。

    5.支持图形界面配置grub,但要安装grub-customizer包,epel源提供该包。

    6.在已进入操作系统环境下,不再提供grub命令,也就是不能进入grub交互式界面,只有在开机时才能进入,算是一大缺憾。

    7.在grub2中没有了好用的find命令,算是另一大缺憾。

    1.1.2 命名习惯和文件路径表示方式

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/Naming-convention.html#Naming-convention

    (fd0)           :表示第一块软盘
    (hd0,msdos2)    :表示第一块硬盘的第二个mbr分区。grub2中分区从1开始编号,传统的grub是从0开始编号的
    (hd0,msdos5)    :表示第一块硬盘的第一个逻辑分区
    (hd0,gpt1)      :表示第一块硬盘的第一个gpt分区
    /boot/vmlinuz   :相对路径,基于根目录,表示根目录下的boot目录下的vmlinuz,
                    :如果设置了根目录变量root为(hd0,msdos1),则表示(hd0,msdos1)/boot/vmlinuz
    (hd0,msdos1)/boot/vmlinuz:绝对路径,表示第一硬盘第一分区的boot目录下的vmlinuz文件

    1.1.3 grub2引导操作系统的方式

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/General-boot-methods.html#General-boot-methods

    grub2支持两种方式引导操作系统:

    • 直接引导:(direct-load)直接通过默认的grub2 boot loader来引导写在默认配置文件中的操作系统
    • 链式引导:(chain-load)使用默认grub2 boot loader链式引导另一个boot loader,该boot loader将引导对应的操作系统

    一般只使用第一种方式,只有想引导grub默认不支持的操作系统时才会使用第二种方式。

    1.1.4 grub2程序和传统grub程序安装后的文件分布

    在传统grub软件安装完后,在/usr/share/grub/RELEASE/目录下会生成一些stage文件。

    [root@xuexi ~]# ls /usr/share/grub/x86_64-redhat/
    e2fs_stage1_5      ffs_stage1_5       jfs_stage1_5       reiserfs_stage1_5  stage2             ufs2_stage1_5      xfs_stage1_5
    fat_stage1_5       iso9660_stage1_5   minix_stage1_5     stage1             stage2_eltorito    vstafs_stage1_5

    在grub2软件安装完后,会在/usr/lib/grub/i386-pc/目录下生成很多模块文件和img文件,还包括一些lst列表文件。

    [root@server7 ~]# ls /usr/lib/grub/i386-pc/*.mod | wc -l
    257
    
    [root@server7 ~]# ls -lh /usr/lib/grub/i386-pc/*.lst   
    -rw-r--r--. 1 root root 3.7K Nov 24  2015 /usr/lib/grub/i386-pc/command.lst
    -rw-r--r--. 1 root root  936 Nov 24  2015 /usr/lib/grub/i386-pc/crypto.lst
    -rw-r--r--. 1 root root  214 Nov 24  2015 /usr/lib/grub/i386-pc/fs.lst
    -rw-r--r--. 1 root root 5.1K Nov 24  2015 /usr/lib/grub/i386-pc/moddep.lst
    -rw-r--r--. 1 root root  111 Nov 24  2015 /usr/lib/grub/i386-pc/partmap.lst
    -rw-r--r--. 1 root root   17 Nov 24  2015 /usr/lib/grub/i386-pc/parttool.lst
    -rw-r--r--. 1 root root  202 Nov 24  2015 /usr/lib/grub/i386-pc/terminal.lst
    -rw-r--r--. 1 root root   33 Nov 24  2015 /usr/lib/grub/i386-pc/video.lst
    
    [root@server7 ~]# ls -lh /usr/lib/grub/i386-pc/*.img
    -rw-r--r--. 1 root root  512 Nov 24  2015 /usr/lib/grub/i386-pc/boot_hybrid.img
    -rw-r--r--. 1 root root  512 Nov 24  2015 /usr/lib/grub/i386-pc/boot.img
    -rw-r--r--. 1 root root 2.0K Nov 24  2015 /usr/lib/grub/i386-pc/cdboot.img
    -rw-r--r--. 1 root root  512 Nov 24  2015 /usr/lib/grub/i386-pc/diskboot.img
    -rw-r--r--. 1 root root  28K Nov 24  2015 /usr/lib/grub/i386-pc/kernel.img
    -rw-r--r--. 1 root root 1.0K Nov 24  2015 /usr/lib/grub/i386-pc/lnxboot.img
    -rw-r--r--. 1 root root 2.9K Nov 24  2015 /usr/lib/grub/i386-pc/lzma_decompress.img
    -rw-r--r--. 1 root root 1.0K Nov 24  2015 /usr/lib/grub/i386-pc/pxeboot.img

    1.1.5 boot loader和grub的关系

    当使用grub来管理启动菜单时,那么boot loader都是grub程序安装的。

    传统的grub将stage1转换后的内容安装到MBR(VBR或EBR)中的boot loader部分,将stage1_5转换后的内容安装在紧跟在MBR后的扇区中,将stage2转换后的内容安装在/boot分区中。

    grub2将boot.img转换后的内容安装到MBR(VBR或EBR)中的boot loader部分,将diskboot.img和kernel.img结合成为core.img,同时还会嵌入一些模块或加载模块的代码到core.img中,然后将core.img转换后的内容安装到磁盘的指定位置处。

    它们之间更具体的关系见下文。

    1.1.6 grub2的安装位置

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html#BIOS-installation

    严格地说是core.img的安装位置,因为boot.img的位置是固定在MBR或VBR或EBR上的。

    (1).MBR

    MBR格式的分区表用于PC BIOS平台,这种格式允许四个主分区和额外的逻辑分区。使用这种格式的分区表,有两种方式安装GURB:

    1. 嵌入到MBR和第一个分区中间的空间,这部分就是大众所称的"boot track","MBR gap"或"embedding area",它们大致需要31kB的空间;
    2. 将core.img安装到某个文件系统中,然后使用分区的第一个扇区(严格地说不是第一个扇区,而是第一个block)存储启动它的代码。

    这两种方法有不同的问题。

    使用嵌入的方式安装grub,就没有保留的空闲空间来保证安全性,例如有些专门的软件就是使用这段空间来实现许可限制的;另外分区的时候,虽然会在MBR和第一个分区中间留下空闲空间,但可能留下的空间会比这更小。

    方法二安装grub到文件系统,但这样的grub是脆弱的。例如,文件系统的某些特性需要做尾部包装,甚至某些fsck检测,它们可能会移动这些block。

    GRUB开发团队建议将GRUB嵌入到MBR和第一个分区之间,除非有特殊需求,但仍必须要保证第一个分区至少是从第31kB(第63个扇区)之后才开始创建的。

    现在的磁盘设备,一般都会有分区边界对齐的性能优化提醒,所以第一个分区可能会自动从第1MB处开始创建。

    (2).GPT

    一些新的系统使用GUID分区表(GPT)格式,这种格式是EFI固件所指定的一部分。但如果操作系统支持的话,GPT也可以用于BIOS平台(即MBR风格结合GPT格式的磁盘),使用这种格式,需要使用独立的BIOS boot分区来保存GRUB,GRUB被嵌入到此分区,不会有任何风险。

    当在gpt磁盘上创建一个BIOS boot分区时,需要保证两件事:(1)它最小是31kB大小,但一般都会为此分区划分1MB的空间用于可扩展性;(2)必须要有合理的分区类型标识(flag type)。

    例如使用gun parted工具时,可以设置为bios_grub标识:

    1

    2

    # parted /dev/sda toggle partition_num bios_grub

    # parted /dev/sda set partiton_num bios_grub on

    如果使用gdisk分区工具时,则分类类型设置为"EF02"。

    如果使用其他的分区工具,可能需要指定guid,则可以指定其guid为"21686148-6449-6e6f-744e656564454649"。

    下图是某个bios/gpt格式的bios boot分区信息,从中可见,它大小为1M,没有文件系统,分区表示为bios_grub。

    下图为gpt磁盘在图形界面下安装操作系统时创建的Bios boot分区。

    1.1.7 进入grub命令行

    在传统的grub上,可以直接在bash下敲入grub命令进入命令交互模式,但grub2只能在系统启动前进入grub交互命令行。

    按下e见可以编辑所选菜单对应的grub菜单配置项,按下c键可以进入grub命令行交互模式。

    1.2 安装grub2

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/Installing-GRUB-using-grub_002dinstall.html#Installing-GRUB-using-grub_002dinstall

    这里的安装指的不是安装grub程序,而是安装Boot loader,但一般都称之为安装grub,且后文都是这个意思。

    1.2.1 grub安装命令

    安装方式非常简单,只需调用grub2-install,然后给定安装到的设备名即可。

    shell> grub2-install /dev/sda

    这样的安装方式,默认会将img文件放入到/boot目录下,如果想自定义放置位置,则使用--boot-directory选项指定,可用于测试练习grub的时候使用,但在真实的grub环境下不建议做任何改动。

    shell> grub2-install --boot-director=/mnt/boot /dev/fd0

    如果是EFI固件平台,则必须挂载好efi系统分区,一般会挂在/boot/efi下,这是默认的,此时可直接使用grub2-install安装。

    shell> grub2-install

    如果不是挂载在/boot/efi下,则使用--efi-directory指定efi系统分区路径。

    shell> grub2-install --efi-directory=/mnt/efi

    grub2-install实际上是一个shell脚本,用于调用其他工具,真正的功能都是其他工具去完成的,所以如果非常熟悉grub内部命令和机制,完全可以不用grub2-install。

    对应传统的grub安装命令为grub-install,用法和grub2-install一样。

    1.2.2 各种img和stage文件的说明

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/Images.html#Images

    img文件是grub2生成的,stage文件是传统grub生成的。下面是各种文件的说明。

    1.2.2.1 grub2中的img文件

    grub2生成了好几个img文件,有些分布在/usr/lib/grub/i386-pc目录下,有些分布在/boot/grub2/i386-pc目录下,它们之间的关系,相信看了下文之后就会明白了。

    下图描述了各个img文件之间的关系。其中core.img是动态生成的,路径为/boot/grub2/i386-pc/core.img,而其他的img则存在于/usr/lib/grub/i386-pc目录下。当然,在安装grub时,boot.img会被拷贝到/boot/grub2/i386-pc目录下。

    (1)boot.img

    在BIOS平台下,boot.img是grub启动的第一个img文件,它被写入到MBR中或分区的boot sector中,因为boot sector的大小是512字节,所以该img文件的大小也是512字节。

    boot.img唯一的作用是读取属于core.img的第一个扇区并跳转到它身上,将控制权交给该扇区的img。由于体积大小的限制,boot.img无法理解文件系统的结构,因此grub2-install将会把core.img的位置硬编码到boot.img中,这样就一定能找到core.img的位置。

    (2)core.img

    core.img根据diskboot.img、kernel.img和一系列的模块被grub2-mkimage程序动态创建。core.img中嵌入了足够多的功能模块以保证grub能访问/boot/grub,并且可以加载相关的模块实现相关的功能,例如加载启动菜单、加载目标操作系统的信息等,由于grub2大量使用了动态功能模块,使得core.img体积变得足够小。

    core.img中包含了多个img文件的内容,包括diskboot.img/kernel.img等。

    core.img的安装位置随MBR磁盘和GPT磁盘而不同,这在上文中已经说明过了。

    (3)diskboot.img

    如果启动设备是硬盘,即从硬盘启动时,core.img中的第一个扇区的内容就是diskboot.img。diskboo.img的作用是读取core.img中剩余的部分到内存中,并将控制权交给kernel.img,由于此时还不识别文件系统,所以将core.img的全部位置以block列表的方式编码,使得diskboot.img能够找到剩余的内容。

    该img文件因为占用一个扇区,所以体积为512字节。

    (4)cdboot.img

    如果启动设备是光驱(cd-rom),即从光驱启动时,core.img中的第一个扇区的的内容就是cdboo.img。它的作用和diskboot.img是一样的。

    (5)pexboot.img

    如果是从网络的PXE环境启动,core.img中的第一个扇区的内容就是pxeboot.img。

    (6)kernel.img

    kernel.img文件包含了grub的基本运行时环境:设备框架、文件句柄、环境变量、救援模式下的命令行解析器等等。很少直接使用它,因为它们已经整个嵌入到了core.img中了。注意,kernel.img是grub的kernel,和操作系统的内核无关。

    如果细心的话,会发现kernel.img本身就占用28KB空间,但嵌入到了core.img中后,core.img文件才只有26KB大小。这是因为core.img中的kernel.img是被压缩过的。

    (7)lnxboot.img

    该img文件放在core.img的最前部位,使得grub像是linux的内核一样,这样core.img就可以被LILO的"image="识别。当然,这是配合LILO来使用的,但现在谁还适用LILO呢?

    (8)*.mod

    各种功能模块,部分模块已经嵌入到core.img中,或者会被grub自动加载,但有时也需要使用insmod命令手动加载。

    1.2.2.2 传统grub中的stage文件

    grub2的设计方式和传统grub大不相同,因此和stage之间的对比关系其实没那么标准,但是将它们拿来比较也有助于理解img和stage文件的作用。

    stage文件也分布在两个地方:/usr/share/grub/RELEASE目录下和/boot/grub目录下,/boot/grub目录下的stage文件是安装grub时从/usr/share/grub/RELEASE目录下拷贝过来的。

    (1)stage1

    stage1文件在功能上等价于boot.img文件。目的是跳转到stage1_5或stage2的第一个扇区上。

    (2)*_stage1_5

    *stage1_5文件包含了各种识别文件系统的代码,使得grub可以从文件系统中读取体积更大功能更复杂的stage2文件。从这一方面考虑,它类似于core.img中加载对应文件系统模块的代码部分,但是core.img的功能远比stage1_5多。

    stage1_5一般安装在MBR后、第一个分区前的那段空闲空间中,也就是MBR gap空间,它的作用是跳转到stage2的第一个扇区。

    其实传统的grub在某些环境下是可以不用stage1_5文件就能正常运行的,但是grub2则不能缺少core.img。

    (3)stage2

    stage2的作用是加载各种环境和加载内核,在grub2中没有完全与之相对应的img文件,但是core.img中包含了stage2的所有功能。

    当跳转到stage2的第一个扇区后,该扇区的代码负责加载stage2剩余的内容。

    注意,stage2是存放在磁盘上的,并没有像core.img一样嵌入到磁盘上。

    (4)stage2_eltorito

    功能上等价于grub2中的core.img中的cdboot.img部分。一般在制作救援模式的grub时才会使用到cd-rom相关文件。

    (5)pxegrub

    功能上等价于grub2中的core.img中的pxeboot.img部分。

    1.2.3 安装grub涉及的过程

    安装grub2的过程大体分两步:一是根据/usr/lib/grub/i386-pc/目录下的文件生成core.img,并拷贝boot.img和core.img涉及的某些模块文件到/boot/grub2/i386-pc/目录下;二是根据/boot/grub2/i386-pc目录下的文件向磁盘上写boot loader。

    当然,到底是先拷贝,还是先写boot loader,没必要去搞清楚,只要/boot/grub2/i386-pc下的img文件一定能通过grub2相关程序再次生成boot loader。所以,既可以认为/boot/grub2/i386-pc目录下的img文件是boot loader的特殊备份文件,也可以认为是boot loader的源文件。

    不过,img文件和boot loader的内容是不一致的,因为img文件还要通过grub2相关程序来转换才是真正的boot loader。

    对于传统的grub而言,拷贝的不是img文件,而是stage文件。

    以下是安装传统grub时,grub做的工作。很不幸,grub2上没有该命令,也没有与之等价的命令。

    grub> setup (hd0)
     Checking if "/boot/grub/stage1" exists... yes
     Checking if "/boot/grub/stage2" exists... yes
     Checking if "/boot/grub/e2fs_stage1_5" exists... yes
     Running "embed /boot/grub/e2fs_stage1_5 (hd0)"...  15 sectors are embedded.
    succeeded
     Running "install /boot/grub/stage1 (hd0) (hd0)1+15 p (hd0,0)/boot/grub/stage2 /boot/grub/menu.lst"... succeeded
    Done.

    首先检测各stage文件是否存在于/boot/grub目录下,随后嵌入stage1_5到磁盘上,该文件系统类型的stage1_5占用了15个扇区,最后安装stage1,并告知stage1 stage1_5的位置是第1到第15个扇区,之所以先嵌入stage1_5再嵌入stage1就是为了让stage1知道stage1_5的位置,最后还告知了stage1 stage2和配置文件menu.lst的路径。

    1.3 grub2配置文件

    grub2的默认配置文件为/boot/grub2/grub.cfg,该配置文件的写法弹性非常大,但绝大多数需要修改该配置文件时,都只需修改其中一小部分内容就可以达成目标。

    grub2-mkconfig程序可用来生成符合绝大多数情况的grub.cfg文件,默认它会自动尝试探测有效的操作系统内核,并生成对应的操作系统菜单项。使用方法非常简单,只需一个选项"-o"指定输出文件即可。

    shell> grub2-mkconfig -o /boot/grub2/grub.cfg

    1.3.1 通过/etc/default/grub文件生成grub.cfg

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/Simple-configuration.html#Simple-configuration

    grub2-mkconfig是根据/etc/default/grub文件来创建配置文件的。该文件中定义的是grub的全局宏,修改内置的宏可以快速生成grub配置文件。实际上在/etc/grub.d/目录下还有一些grub配置脚本,这些shell脚本读取一些脚本配置文件(如/etc/default/grub),根据指定的逻辑生成grub配置文件。若有兴趣,不放读一读/etc/grub.d/10_linux文件,它指导了创建grub.cfg的细节,例如如何生成启动菜单。

    [root@xuexi ~]# ls /etc/grub.d/
    00_header  00_tuned  01_users  10_linux  20_linux_xen  20_ppc_terminfo  30_os-prober  40_custom  41_custom  README

    在/etc/default/grub中,使用"key=vaule"的格式,key全部为大小字母,如果vaule部分包含了空格或其他特殊字符,则需要使用引号包围。

    例如,下面是一个/etc/default/grub文件的示例:

    [root@xuexi ~]# cat /etc/default/grub
    GRUB_TIMEOUT=5
    GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
    GRUB_DEFAULT=saved
    GRUB_DISABLE_SUBMENU=true
    GRUB_TERMINAL_OUTPUT="console"
    GRUB_CMDLINE_LINUX="crashkernel=auto biosdevname=0 net.ifnames=0 rhgb quiet"
    GRUB_DISABLE_RECOVERY="true"

    虽然可用的宏较多,但可能用的上的就几个:GRUB_DEFAULT、GRUB_TIMEOUT、GRUB_CMDLINE_LINUX和GRUB_CMDLINE_LINUX_DEFAULT。

    以下列出了部分key。

    (1).GRUB_DEFAULT

    默认的菜单项,默认值为0。其值可为数值N,表示从0开始计算的第N项是默认菜单,也可以指定对应的title表示该项为默认的菜单项。使用数值比较好,因为使用的title可能包含了容易改变的设备名。例如有如下菜单项:

    1

    2

    3

    menuentry 'Example GNU/Linux distribution' --class gnu-linux --id example-gnu-linux {

        ...

    }

    如果想将此菜单设为默认菜单,则可设置"GRUB_DEFAULT=example-gnu-linux"。

    如果GRUB_DEFAULT的值设置为"saved",则表示默认的菜单项是"GRUB_SAVEDEFAULT"或"grub-set-default"所指定的菜单项。

    (2).GRUB_SAVEDEFAULT

    默认该key的值未设置。如果该key的值设置为true时,如果选定了某菜单项,则该菜单项将被认为是新的默认菜单项。该key只有在设置了"GRUB_DEFAULT=saved"时才有效。

    不建议使用该key,因为GRUB_DEFAULT配合grub-set-default更方便。

    (3).GRUB_TIMEOUT

    在开机选择菜单项的超时时间,超过该时间将使用默认的菜单项来引导对应的操作系统。默认值为5秒。等待过程中,按下任意按键都可以中断等待。

    设置为0时,将不列出菜单直接使用默认的菜单项引导与之对应的操作系统,设置为"-1"时将永久等待选择。

    是否显示菜单,和"GRUB_TIMEOUT_STYLE"的设置有关。

    (4).GRUB_TIMEOUT_STYLE

    如果该key未设置值或者设置的值为"menu",则列出启动菜单项,并等待"GRUB_TIMEOUT"指定的超时时间。

    如果设置为"countdown"和"hidden",则不显示启动菜单项,而是直接等待"GRUB_TIMEOUT"指定的超时时间,如果超时了则启动默认菜单项并引导对应的操作系统。在等待过程中,按下"ESC"键可以列出启动菜单。设置为countdown和hidden的区别是countdown会显示超时时间的剩余时间,而hidden则完全隐藏超时时间。

    (5).GRUB_DISTRIBUTOR

    设置发行版的标识名称,一般该名称用来作为菜单的一部分,以便区分不同的操作系统。

    (6).GRUB_CMDLINE_LINUX

    添加到菜单中的内核启动参数。例如:

    GRUB_CMDLINE_LINUX="crashkernel=ro root=/dev/sda3 biosdevname=0 net.ifnames=0 rhgb quiet"

    (7).GRUB_CMDLINE_LINUX_DEFAULT

    除非"GRUB_DISABLE_RECOVERY"设置为"true",否则该key指定的默认内核启动参数将生成两份,一份是用于默认启动参数,一份用于恢复模式(recovery mode)的启动参数。

    该key生成的默认内核启动参数将添加在"GRUB_CMDLINE_LINUX"所指定的启动参数之后。

    (8).GRUB_DISABLE_RECOVERY

    该项设置为true时,将不会生成恢复模式的菜单项。

    (9).GRUB_DISABLE_LINUX_UUID

    默认情况下,grub2-mkconfig在生产菜单项的时候将使用uuid来标识Linux 内核的根文件系统,即"root=UUID=..."。

    例如,下面是/boot/grub2/grub.cfg中某菜单项的部分内容。

    menuentry 'CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8' {

            ......

            linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8 ro crashkernel=auto biosdevname=0 net.ifnames=0 quiet LANG=en_US.UTF-8

            initrd16 /initramfs-3.10.0-327.el7.x86_64.img

    }

    虽然使用UUID的方式更可靠,但有时候不太方便,所以可以设置该key为true来禁用。

    (10).GRUB_BACKGROUND

    设置背景图片,背景图片必须是grub可读的,图片文件名后缀必须是".png"、".tga"、".jpg"、".jpeg",在需要的时候,grub会按比例缩小图片的大小以适配屏幕大小。

    (11).GRUB_THEME

    设置grub菜单的主题。

    (12).GRUB_GFXPAYLOAD_LINUX

    设置为"text"时,将强制使用文本模式启动Linux。在某些情况下,可能不支持图形模式。

    (13).GRUB_DISABLE_OS_PROBER

    默认情况下,grub2-mkconfig会尝试使用os-prober程序(如果已经安装的话,默认应该都装了)探测其他可用的操作系统内核,并为其生成对应的启动菜单项。设置为"true"将禁用自动探测功能。

    (14).GRUB_DISABLE_SUBMENU

    默认情况下,grub2-mkconfig如果发现有多个同版本的或低版本的内核时,将只为最高版本的内核生成顶级菜单,其他所有的低版本内核菜单都放入子菜单中,设置为"y"将全部生成为顶级菜单。

    (15).GRUB_HIDDEN_TIMEOUT(已废弃,但为了向后兼容,仍有效)

    使用"GRUB_TIMEOUT_STYLE={countdown|hidden}"替代该项

    (16).GRUB_HIDDEN_TIMEOUT_QUIET(已废弃,但为了向后兼容,仍有效)

    配合GRUB_HIDDEN_TIMEOUT使用,可以使用GRUB_TIMEOUT_STYLE=countdown来替代这两项。

    1.3.2 脚本方式直接编写grub.cfg文件

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/Shell_002dlike-scripting.html#Shell_002dlike-scripting

    • 注释符:从#开始的字符都被认为是注释,所以grub支持行中注释
    • 连接操作符:{ } | & $ ; < >
    • 保留关键字和符号:! [[ ]] { } case do done elif else esac fi for function if in menuentry select then time until while。并非所有的关键字都有用,只是为了日后的功能扩展而提前提供的。
    • 引号和转义符

    对于特殊的字符需要转义。有三种方式转义:使用反斜线、使用单引号、使用双引号。

    反斜线转义方式和shell一样。

    单引号中的所有字符串都是字面意思,没有任何特殊意义,即使单引号中的转义符也被认为是纯粹的字符。所以'\''是无法保留单引号的。单引号需要使用双引号来转移,所以应该写"'"。

    双引号和单引号作用一样,但它不能转义某几个特殊字符,包括"$"和"\"。对于双引号中的"$"符号,它任何时候都保留本意。对于"\",只有反斜线后的字符是'$'、'"'、'\'时才表示转义的意思,另外 ,某行若以反斜线结尾,则表示续行,但官方不建议在grub.cfg中使用续行符。

    • 变量扩展

    使用$符号引用变量,也可以使用${var}的方式引用var变量。

    支持位置变量,例如$1引用的是第一个参数。

    还支持特殊的变量,如$?表示上一次命令的退出状态码。如果使用了位置变量,则还支持$*、$@和$#,$*代表的所有参数整体,各参数之间是不可分割的,$@也代表所有变量,但$@的各参数是可以被分割的,$#表示参数的个数。

    • 简单的命令

    可以在grub.cfg中使用简单的命令。各命令之间使用换行符或分号表示该命令结束。

    如果在命令前使用了"!",则表示逻辑取反。

    • 循环结构:for name in word …; do list; done
    • 循环结构:while cond; do list; done
    • 循环结构:until cond; do list; done
    • 条件判断结构:if list; then list; [elif list; then list;] … [else list;] fi
    • 函数结构:function name { command; … }
    • 菜单项命令:menuentry title [--class=class …] [--users=users] [--unrestricted] [--hotkey=key] [--id=id] { command; … }

    这是grub.cfg中最重要的项,官方原文:https://www.gnu.org/software/grub/manual/html_node/menuentry.html#menuentry

    该命令定义了一个名为title的grub菜单项。当开机时选中该菜单项时,grub会将chosen环境变量的值赋给"--id"(如果给定了"--id"的话),执行大括号中的命令列表,如果直到最后一个命令都全部执行成功,且成功加载了对应的内核后,将执行boot命令。随后grub就将控制权交给了操作系统内核。

    --class:该选项用于将菜单分组,从而使得grub可以通过主题样式为不同组的菜单显示不同的样式风格。一个menuentry中,可以使用多次class表示将该菜单分到多个组中去。

    --users:该选项限定只有此处列出的用户才能访问该菜单项,不指定该选项时将表示所有用户都能访问该菜单。

    --unrestricted:该选项表示所有用户都有权访问该菜单项。

    --hotkey:该选项为该菜单项关联一个热键,也就是快捷键,关联热键后只要按下该键就会选中该菜单。热键只能是字母键、backspace键、tab键或del键。

    --id:该选项为该菜单关联一个唯一的数值。id的值可以由ASCII字母、数字//下划线组成,且不得以数字开头。

    所有其他的参数包括title都被当作位置参数传递给大括号中的命令,但title总是$1,除title外的其余参数,位置值从前向后类推。

    • break [n]:强制退出for/while/until循环
    • continue [n]:跳到下一次迭代,即进入下一次循环
    • return [n]:指定返回状态码
    • setparams [arg] …:从$1开始替换位置参数
    • shift [n]:踢掉前n个参数,使得第n+1个参数变为$1,但和shell中不一样的是,踢掉了前n个参数后,从$#-n+1到$#这些参数的位置不变

    具体如何编写grub.cfg文件,继续看下文的命令和变量。

    1.4 命令行和菜单项中的命令

    官方手册原文:https://www.gnu.org/software/grub/manual/html_node/Commands.html#Commands

    grub2支持很多命令,有些命令只能在交互式命令行下使用,有些命令可用在配置文件中。在救援模式下,只有insmod、ls、set和unset命令可用。

    无需掌握所有的命令,掌握用的上的几个命令即可。

    1.4.1 help命令

    1

    help [pattern]

    显示能匹配到pattern的所有命令的说明信息和usage信息,如果不指定patttern,将显示所有命令的简短信息。

    例如"help cmos"。

    1.4.2 boot命令

    用于启动已加载的操作系统。

    只在交互式命令行下可用。其实在menuentry命令的结尾就隐含了boot命令。

    1.4.3 set和unset命令

    1

    2

    set [envvar=value]

    unset envvar

    前者设置环境变量envvar的值,如果不给定参数,则列出当前环境变量。

    后者释放环境变量envvar。

    1.4.4 lsmod命令和insmod命令

    分别用于列出已加载的模块和调用指定的模块。

    注意,若要导入支持ext文件系统的模块时,只需导入ext2.mod即可,实际上也没有ext3和ext4对应的模块。

    1.4.5 linux和linux16命令

    1

    2

    linux file [kernel_args]

    linux16 file [kernel_args]

    都表示装载指定的内核文件,并传递内核启动参数。linux16表示以传统的16位启动协议启动内核,linux表示以32位启动协议启动内核,但linux命令比linux16有一些限制。但绝大多数时候,它们是可以通用的。

    在linux或linux16命令之后,必须紧跟着使用init或init16命令装载init ramdisk文件。

    一般为/boot分区下的vmlinuz-RELEASE_NUM文件。

    但在grub环境下,boot分区被当作root分区,即根分区,假如boot分区为第一块磁盘的第一个分区,则应该写成:

    linux (hd0,msdos1)/vmlinuz-XXX

    或者相对路径的:

    set root='hd0,msdos1'

    linux /vmlinuz-XXX

    在grub阶段可以传递内核的启动参数(内核的参数包括3类:编译内核时参数,启动时参数和运行时参数),可以传递的启动参数非常非常多,完整的启动参数列表见:http://redsymbol.net/linux-kernel-boot-parameters。这里只列出几个常用的:

    init=   :指定Linux启动的第一个进程init的替代程序。
    root=   :指定根文件系统所在分区,在grub中,该选项必须给定。
    ro,rw   :启动时,根分区以只读还是可读写方式挂载。不指定时默认为ro。
    initrd  :指定init ramdisk的路径。在grub中因为使用了initrd或initrd16命令,所以不需要指定该启动参数。
    rhgb    :以图形界面方式启动系统。
    quiet   :以文本方式启动系统,且禁止输出大多数的log message。
    net.ifnames=0:用于CentOS 7,禁止网络设备使用一致性命名方式。
    biosdevname=0:用于CentOS 7,也是禁止网络设备采用一致性命名方式。
                 :只有net.ifnames和biosdevname同时设置为0时,才能完全禁止一致性命名,得到eth0-N的设备名。

    例如:

    linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=edb1bf15-9590-4195-aa11-6dac45c7f6f3 ro rhgb quiet LANG=en_US.UTF-8

    另外,root启动参数有多种定义方式,可以使用UUID的方式指定,也可以直接指定根文件系统所在分区,如"root=/dev/sda2",

    1.4.6 initrd和initrd16命令

    1

    initrd file

    只能紧跟在linux或linux16命令之后使用,用于为即将启动的内核传递init ramdisk路径。

    同样,基于根分区,可以使用绝对路径,也可以使用相对路径。路径的表示方法和linux或linux16命令相同。例如:

    linux16 /vmlinuz-0-rescue-d13bce5e247540a5b5886f2bf8aabb35 root=UUID=b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8 ro crashkernel=auto quiet

    initrd16 /initramfs-0-rescue-d13bce5e247540a5b5886f2bf8aabb35.img

    1.4.7 search命令

    1

    search [--file|--label|--fs-uuid] [--set [var]] [--no-floppy] [--hint args] name

    通过文件[--file]、卷标[--label]、文件系统UUID[--fs-uuid]来搜索设备。

    如果使用了"--set"选项,则会将第一个找到的设备设置为环境变量"var"的值,默认的变量"var"为'root'。

    搜索时可使用"--no-floppy"选项来禁止搜索软盘,因为软盘速度非常慢,已经被淘汰了。

    有时候还会指定"--hint=XXX",表示优先选择满足提示条件的设备,若指定了多个hint条件,则优先匹配第一个hint,然后匹配第二个,依次类推。

    例如:

    if [ x$feature_platform_search_hint = xy ]; then

      search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  367d6a77-033b-4037-bbcb-416705ead095

    else

      search --no-floppy --fs-uuid --set=root 367d6a77-033b-4037-bbcb-416705ead095

    fi

    linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8 ro crashkernel=auto quiet LANG=en_US.UTF-8

    initrd16 /initramfs-3.10.0-327.el7.x86_64.img

    上述if语句中的第一个search中搜索uuid为"367d6a77-033b-4037-bbcb-416705ead095"的设备,但使用了多个hint选项,表示先匹配bios平台下/boot分区为(hd0,msdos1)的设备,之后还指定了几个hint,但因为search使用的是uuid搜索方式,所以这些hint选项是多余的,因为单磁盘上分区的uuid是唯一的。

    再举个例子,如果某启动设备上有两个boot分区(如多系统共存时),分别是(hd0,msdos1)和(hd0,msdos5),如果此时不使用uuid搜索,而是使用label方式搜索:

    search --no-floppy --fs-label=boot --set=root --hint=hd0,msdos5

    则此时将会选中(hd0,msdos5)这个boot分区,若不使用hint,将选中(hd0,msdos1)这个boot分区。

    1.4.8 true和false命令

    直接返回true或false布尔值。

    1.4.9 test expression和[ expression ]

    计算"expression"的结果是否为真,为真时返回0,否则返回非0,主要用于if、while或until结构中。

    string1 == string2

    string1与string2相同

    string1 != string2

    string1与string2不相同

    string1 < string2

    string1在字母顺序上小于string2

    string1 <= string2

    string1在字母顺序上小于等于string2

    string1 > string2

    string1在字母顺序上大于string2

    string1 >= string2

    string1在字母顺序上大于等于string2

    integer1 -eq integer2

    integer1等于integer2

    integer1 -ge integer2

    integer1大于或等于integer2

    integer1 -gt integer2

    integer1大于integer2

    integer1 -le integer2

    integer1小于或等于integer2

    integer1 -lt integer2

    integer1小于integer2

    integer1 -ne integer2

    integer1不等于integer2

    prefixinteger1 -pgt prefixinteger2

    剔除非数字字符串prefix部分之后,integer1大于integer2

    prefixinteger1 -plt prefixinteger2

    剔除非数字字符串prefix部分之后,integer1小于integer2

    file1 -nt file2

    file1的修改时间比file2新

    file1 -ot file2

    file1的修改时间比file2旧

    -d file

    file存在且是目录

    -e file

    file存在

    -f file

    file存在并且不是一个目录

    -s file

    file存在并且文件占用空间大于零

    -n string

    string的长度大于零

    string   

    string的长度大于零,等价于-n string

    -z string

    string的长度等于零

    ( expression )

    将expression作为一个整体

    ! expression  

    非(NOT)

    expression1 -a expression2

    与(AND),也可以使用expression1 expression2,但不推荐

    expression1 -o expression2

    或(OR)

    1.4.10 cat命令

    读取文件内容,借此可以帮助判断哪个是boot分区,哪个是根分区。

    交互式命令行下使用。

    1.4.11 clear命令

    清屏。

    1.4.12 configfile命令

    立即装载一个指定的文件作为grub的配置文件。但注意,导入的文件中的环境变量不在当前生效。

    在grub.cfg丢失时,该命令将排上用场。

    1.4.13 echo命令

    1

    echo [-n] [-e] string

    "-n"和"-e"用法同shell中echo。如果要引用变量,使用${var}的方式。

    1.4.14 export命令

    导出环境变量,若在configfile的file中导出环境变量,将会在当前环境也生效。

    1.4.15 halt和reboot命令

    关机或重启

    1.4.16 ls命令

    1

    ls [args]

    如果不给定任何参数,则列出grub可见的设备。

    如果给定的参数是一个分区,则显示该分区的文件系统信息。

    如果给定的参数是一个绝对路径表示的目录,则显示该目录下的所有文件。

    例如:

    1.4.17 probe命令

    1

    probe [--set var] --partmap|--fs|--fs-uuid|--label device

    探测分区或磁盘的属性信息。如果未指定--set,则显示指定设备对应的信息。如果指定了--set,则将对应信息的值赋给变量var。

    --partmap:显示是gpt还是mbr格式的磁盘。

    --fs:显示分区的文件系统。

    --fs-uuid:显示分区的uuid值。

    --label:显示分区的label值。

    1.4.18 save_env和list_env命令

    将环境变量保存到环境变量块中,以及列出当前的环境变量块中的变量。

    1.4.19 loopback命令

    1

    loopback [-d] device file

    将file映射为回环设备。使用-d选项则是删除映射。

    例如:

    loopback loop0 /path/to/image
    ls (loop0)/

    1.4.20 normal和normal_exit命令

    进入和退出normal模式,normal是相对于救援模式而言的,只要不是在救援模式下,就是在normal模式下。

    救援模式下,只能使用非常少的命令,而normal模式下则可以使用非常多的命令。

    1.4.21 password和password_pbkdf2命令

    1

    2

    password user clear-password

    password_pbkdf2 user hashed-password

    前者使用明文密码定义一个名为user的用户。不建议使用此命令。

    后者使用哈希加密后的密码定义一个名为user的用户,加密的密码通过"grub-mkpasswd-pbkdf2"工具生成。建议使用该命令。

    1.5 几个常设置的内置变量

    1.5.1 chosen变量

    当开机时选中某个菜单项启动时,该菜单的title将被赋值给chosen变量。该变量一般只用于引用,而不用于修改。

    1.5.2 cmdpath变量

    grub2加载的core.img的目录路径,是绝对路径,即包括了设备名的路径,如(hd0,gpt1)/boot/grub2/。该变量值不应该修改。

    1.5.3 default变量

    指定默认的菜单项,一般其后都会跟随timeout变量。

    default指定默认菜单时,可使用菜单的title,也可以使用菜单的id,或者数值顺序,当使用数值顺序指定default时,从0开始计算。

    1.5.4 timeout变量

    设置菜单等待超时时间,设置为0时将直接启动默认菜单项而不显示菜单,设置为"-1"时将永久等待手动选择。

    1.5.5 fallback变量

    当默认菜单项启动失败,则使用该变量指定的菜单项启动,指定方式同default,可使用数值(从0开始计算)、title或id指定。

    1.5.6 grub_platform变量

    指定该平台是"pc"还是"efi",pc表示的就是传统的bios平台。

    该变量不应该被修改,而应该被引用,例如用于if判断语句中。

    1.5.7 prefix变量

    在grub启动的时候,grub自动将/boot/grub2目录的绝对路径赋值给该变量,使得以后可以直接从该变量所代表的目录下加载各文件或模块。

    例如,可能自动设置为:

    set prefix = (hd0,gpt1)/boot/grub2/

    所以可以使用"$prefix/grubN.cfg"来引用/boot/grub2/grubN.cfg文件。

    该变量不应该修改,且若手动设置,则必须设置正确,否则牵一发而动全身。

    1.5.8 root变量

    该变量指定根设备的名称,使得后续使用从"/"开始的相对路径引用文件时将从该root变量指定的路径开始。一般该变量是grub启动的时候由grub根据prefix变量设置而来的。

    例如prefix=(hd0,gpt1)/boot/grub2,则root=(hd0,gpt1),后续就可以使用相对路径/vmlinuz-XXX表示(hd0,gpt1)/vmlinuz-XXX文件。

    注意:在Linux中,从根"/"开始的路径表示绝对路径,如/etc/fstab。但grub中,从"/"开始的表示相对路径,其相对的基准是root变量设置的值,而使用"(dev_name)/"开始的路径才表示绝对路径。

    一般root变量都表示/boot所在的分区,但这不是绝对的,如果设置为根文件系统所在分区,如root=(hd0,gpt2),则后续可以使用/etc/fstab来引用"(hd0,gpt2)/etc/fstab"文件。

    该变量在grub2中一般不用修改,但若修改则必须指定正确。

    另外,root变量还应该于linux或linux16命令所指定的内核启动参数"root="区分开来,内核启动参数中的"root="的意义是固定的,其指定的是根文件系统所在分区。例如:

    set root='hd0,msdos1'

    linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8 ro crashkernel=auto quiet LANG=en_US.UTF-8

    initrd16 /initramfs-3.10.0-327.el7.x86_64.img

    一般情况下,/boot都会单独分区,所以root变量指定的根设备和root启动参数所指定的根分区不是同一个分区,除非/boot不是单独的分区,而是在根分区下的一个目录。

    1.6 grub配置和安装示例

    首先写一个grub.cfg。例如此处,在msdos磁盘上安装了两个操作系统,CentOS 7和CentOS 6。

    # 设置一些全局环境变量
    set default=0
    set fallback=1
    set timeout=3
    
    # 将可能使用到的模块一次性装载完
    # 支持msdos的模块
    insmod part_msdos
    # 支持各种文件系统的模块
    insmod exfat
    insmod ext2
    insmod xfs
    insmod fat
    insmod iso9660
    
    # 定义菜单
    menuentry 'CentOS 7' --unrestricted {
            search --no-floppy --fs-uuid --set=root 367d6a77-033b-4037-bbcb-416705ead095
            linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8 ro biosdevname=0 net.ifnames=0 quiet
            initrd16 /initramfs-3.10.0-327.el7.x86_64.img
    }
    menuentry 'CentOS 6' --unrestricted {
            search --no-floppy --fs-uuid --set=root f5d8939c-4a04-4f47-a1bc-1b8cbabc4d32
            linux16 /vmlinuz-2.6.32-504.el6.x86_64 root=UUID=edb1bf15-9590-4195-aa11-6dac45c7f6f3 ro quiet
            initrd16 /initramfs-2.6.32-504.el6.x86_64.img
    }

    然后执行grub安装操作。

    shell> grub2-install /dev/sda

    1.7 传统grub简述

    因为本文主要介绍grub2,所以传统的grub只简单介绍下,其实前面已经提及了很多传统grub和grub2的比较了。另外,传统grub已足够强大,足够应付一般的需求。

    1.7.1 grub安装

    例如安装到/dev/sda上。

    shell> grub-install /dev/sda

    1.7.2 grub.conf配置

    default=0  # 默认启动第一个系统
    timeout=5  # 等待超时时间5秒
    splashimage=(hd0,0)/grub/splash.xpm.gz  # 背景图片
    hiddenmenu  # 隐藏菜单,若要显式,在启动时按下ESC
    title Red Hat Enterprise Linux AS (2.6.18-92.el5)  # 定义操作系统的说明信息
        root (hd0,0) 
        kernel /vmlinuz-2.6.18-92.el5 ro root=/dev/sda2 rhgb quiet
        initrd /initrd-2.6.18-92.el5.img

    在说明配置方法之前,需要说明一个关键点,boot是否是一个独立的分区,它影响后面路径的配置。

    在一个正常的操作系统中查看/boot/grub/grub.conf文件,可以在NOTICE段看到提示,说你是否拥有一个独立的boot分区?如果有则意味着kernel和initrd的路径是从/开始的而不是/boot开始的,如/vmlinuz-xxx,如果没有独立的boot分区,则kernel和initrd的路径中需要指明boot路径,例如Boot没有分区而是在/文件系统下的一个目录,则/boot/vmlinuz-xxx。

    root (hd0,0)定义grub识别的根。一般定义的都是boot所在的分区,grub只能识别hd,所以这里只能使用hd,hd0表示在第一块磁盘上,hd0,0的第二个0表示boot在第一个分区上,grub2在分区的计算上是从1开始的,这是传统grub和grub2不同的地方。

    kernel定义内核文件的路径和启动参数,等价于grub2的linux命令或linux16命令。首先说明参数,ro表示只读,root=/dev/sda[N]或者root=UUID="device_uuid_num"指定根文件系统所在的分区,这是必须的参数。rhgb表示在操作系统启动过程中使用图形界面输出一些信息,将其省略可以加快启动速度,quiet表示启动操作系统时静默输出信息。再说明路径,如果是boot是独立分区的,则kernel的路径定义方式为/vmlinuz-xxx,如果没有独立分区,则指明其绝对路径,一般都是在根文件系统下的目录,所以一般为/boot/vmlinuz-xxx。

    initrd定义init ramdisk的路径,路径的定义方式同kernel。除了路径之外没有任何参数。

    或者使用下图的UUID的方式。

    如果没有指定root=的选项,将报错“no or empty root …… dracut…kernel panic”的错误。如下图。

     

    本文原创地址在博客园:https://www.cnblogs.com/f-ck-need-u/archive/2017/06/29/7094693.html

    展开全文
  • Linux学习:Linux启动管理器GRUB2

    万次阅读 2018-11-06 16:28:46
    引用:《鸟哥的Linux私房菜基础篇第三...所以,底下我们会先谈一谈 boot loader 的功能,然后再讲一讲现阶段 Linux 里头最主流的 grub2 这个 boot loader 吧! 另外,你也得要知道,目前新版的 CentOS 7.x 已经将...

     

    引用:《鸟哥的Linux私房菜基础篇第三版》

    boot loader 是载入核心的重要工具,没有 boot loader 的话,那么 kernel 根本就没有办法被系统加载的呢!所以,底下我们会先谈一谈 boot loader 的功能,然后再讲一讲现阶段 Linux 里头最主流的 grub2 这个 boot loader 吧!

    另外,你也得要知道,目前新版的 CentOS 7.x 已经将沿用多年的 grub 换成了 grub2 了!这个 grub2 版本在配置与安装上面跟之前的 grub 有点不那么相同, 所以,在后续的章节中,得要了解一下新的 grub2 的配置方式才行喔!如果你是新接触者,那没关系~直接看就 OK 了!

    boot loader 的两个 stage

    启动的过程中,在 BIOS 读完信息后,接下来就是会到第一个启动设备的 MBR 去读取 boot loader 了。这个 boot loader 可以具有选单功能、直接加载核心文件以及控制权移交的功能等, 系统必须要有 loader 才有办法加载该操作系统的核心就是了。但是我们都知道, MBR 是整个硬盘的第一个 sector 内的一个区块,充其量整个大小也才 446 bytes 而已。即使是 GPT 也没有很大的扇区来储存 loader 的数据。 我们的 loader 功能这么强,光是程序代码与配置数据不可能只占这么一点点的容量吧?那如何安装?

    为了解决这个问题,所以 Linux 将 boot loader 的程序代码执行与配置值加载分成两个阶段 (stage) 来执行:

    • Stage 1:执行 boot loader 主程序:
      第一阶段为执行 boot loader 的主程序,这个主程序必须要被安装在启动区,亦即是 MBR 或者是 boot sector 。但如前所述,因为 MBR 实在太小了,所以,MBR 或 boot sector 通常仅安装 boot loader 的最小主程序, 并没有安装 loader 的相关配置文件;
    • Stage 2:主程序加载配置文件:
      第二阶段为通过 boot loader 加载所有配置文件与相关的环境参数文件 (包括文件系统定义与主要配置文件 grub.cfg), 一般来说,配置文件都在 /boot 下面。

    那么这些配置文件是放在哪里啊?这些与 grub2 有关的文件都放置到 /boot/grub2 中,那我们就来看看有哪些文件吧!

    [root@study ~]# ls -l /boot/grub2

    -rw-r--r--.  device.map            <==grub2 的设备对应文件(下面会谈到)

    drwxr-xr-x.  fonts                 <==启动过程中的画面会使用到的字体数据

    -rw-r--r--.  grub.cfg              <==grub2 的主配置文件!相当重要!

    -rw-r--r--.  grubenv               <==一些环境区块的符号

    drwxr-xr-x.  i386-pc               <==针对一般 x86 PC所需要的 grub2 的相关模块

    drwxr-xr-x.  locale                <==就是语言相关的数据啰

    drwxr-xr-x.  themes                <==一些启动主题画面数据

     

    [root@study ~]# ls -l /boot/grub2/i386-pc

    -rw-r--r--.  acpi.mod              <==电源管理有关的模块

    -rw-r--r--.  ata.mod               <==磁盘有关的模块

    -rw-r--r--.  chain.mod             <==进行 loader 控制权移交的相关模块

    -rw-r--r--.  command.lst           <==一些指令相关性的列表

    -rw-r--r--.  efiemu32.o            <==下面几个则是与 uefi BIOS 相关的模块

    -rw-r--r--.  efiemu64.o

    -rw-r--r--.  efiemu.mod

    -rw-r--r--.  ext2.mod              <==EXT 文件系统家族相关模块

    -rw-r--r--.  fat.mod               <==FAT 文件系统模块

    -rw-r--r--.  gcry_sha256.mod       <==常见的加密模块

    -rw-r--r--.  gcry_sha512.mod

    -rw-r--r--.  iso9660.mod           <==光盘文件系统模块

    -rw-r--r--.  lvm.mod               <==LVM 文件系统模块

    -rw-r--r--.  mdraid09.mod          <==软件磁盘阵列模块

    -rw-r--r--.  minix.mod             <==MINIX 相关文件系统模块

    -rw-r--r--.  msdospart.mod         <==一般 MBR 分区表

    -rw-r--r--.  part_gpt.mod          <==GPT 分区表

    -rw-r--r--.  part_msdos.mod        <==MBR 分区表

    -rw-r--r--.  scsi.mod              <==SCSI 相关模块

    -rw-r--r--.  usb_keyboard.mod      <==下面两个为 USB 相关模块

    -rw-r--r--.  usb.mod

    -rw-r--r--.  vga.mod               <==VGA 显示适配器相关模块

    -rw-r--r--.  xfs.mod               <==XFS 文件系统模块

    # 鸟哥这里只拿一些模块作说明,没有全部的文件都列上来喔!

    从上面的说明你可以知道 /boot/grub2/ 目录下最重要的就是配置文件 (grub2.cfg) 以及各种文件系统的定义! 我们的 loader 读取了这种文件系统定义数据后,就能够认识文件系统并读取在该文件系统内的核心文件啰。

    所以从上面的文件来看, grub2 认识的文件系统与磁盘分区格式真的非常多喔!正因为如此,所以 grub2 才会取代 Lilo / grub 这个老牌的 boot loader 嘛!好了,接下来就来瞧瞧配置文件内有啥配置值吧!

    grub2 的配置文件 /boot/grub2/grub.cfg 初探

    grub2 的优点挺多的,包括有:

    • 认识与支持较多的文件系统,并且可以使用 grub2 的主程序直接在文件系统中搜寻核心文件名;
    • 启动的时候,可以『自行编辑与修改启动配置项目』,类似 bash 的指令模式;
    • 可以动态搜寻配置文件,而不需要在修改配置文件后重新安装 grub2 。亦即是我们只要修改完 /boot/grub2/grub.cfg 里头的配置后,下次启动就生效了!

    上面第三点其实就是 Stage 1, Stage 2 分别安装在 MBR (主程序) 与文件系统当中 (配置文件与定义文件) 的原因啦! 好了,接下来,让我们好好了解一下 grub2 的配置文件: /boot/grub2/grub.cfg 这玩意儿吧!

    • 磁盘与分区在 grub2 中的代号

    安装在 MBR 的 grub2 主程序,最重要的任务之一就是从磁盘当中加载核心文件, 以让核心能够顺利的驱动整个系统的硬件。所以啰, grub2 必须要认识硬盘才行啊!那么 grub2 到底是如何认识硬盘的呢? 嘿嘿! grub2 对硬盘的代号配置与传统的 Linux 磁盘代号可完全是不同的!grub2 对硬盘的识别使用的是如下的代号:

    (hd0,1)         # 一般的默认语法,由 grub2 自动判断分区格式

    (hd0,msdos1)    # 此磁盘的分区为传统的 MBR 模式

    (hd0,gpt1)      # 此磁盘的分区为 GPT 模式

    够神了吧?跟 /dev/sda1 风马牛不相干~怎么办啊?其实只要注意几个东西即可,那就是:

    • 硬盘代号以小括号 ( ) 包起来;
    • 硬盘以 hd 表示,后面会接一组数字;
    • 以『搜寻顺序』做为硬盘的编号!(这个重要!)
    • 第一个搜寻到的硬盘为 0 号,第二个为 1 号,以此类推;
    • 每颗硬盘的第一个 partition 代号为 1 ,依序类推。

    所以说,第一颗『搜寻到的硬盘』代号为:『(hd0)』,而该颗硬盘的第一号分区为『(hd0,1)』,这样说了解了吧? 另外,为了区分不同的分区格式,因此磁盘后面的分区号码可以使用类似 msdos1 与 gpt1 的方式来调整! 最终要记得的是,磁盘的号码是由 0 开始编号,分区的号码则与 Linux 一样,是由 1 号开始编号!两者不同喔!

    Tips

    跟旧版的 grub 有点不一样,因为旧版的 grub 不论磁盘还是分区的起始号码都是 0 号,而 grub2 在分区的部份是以 1 号开始编喔! 此外,由于 BIOS 可以调整磁盘的启动顺序,因此上述的磁盘对应的 (hdN) 那个号码 N 是可能会变动的喔!这要先有概念才行!

    所以说,整个硬盘代号为:

    硬盘搜寻顺序

    在 Grub2 当中的代号

    第一颗(MBR)

    (hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3)....

    第二颗(GPT)

    (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3)....

    第三颗

    (hd2) (hd2,1) (hd2,2) (hd2,3)....

    这样应该比较好看出来了吧?第一颗硬盘的 MBR 安装处的硬盘代号就是『(hd0)』, 而第一颗硬盘的第一个分区的 boot sector 代号就是『(hd0,msdos1)』第一颗硬盘的第一个逻辑分区的 boot sector 代号为『(hd0,msdos5)』瞭了吧!

    例题:

    假设你的系统仅有一颗 SATA 硬盘,请说明该硬盘的第一个逻辑分区在 Linux 与 grub2 当中的文件名与代号:

    答:

    因为是 SATA 磁盘,加上使用逻辑分区,因此 Linux 当中的文件名为 /dev/sda5 才对 (1~4 保留给 primary 与 extended 使用)。 至于 grub2 当中的磁盘代号则由于仅有一颗磁盘,因此代号会是『 (hd0,msdos5) 』或简易的写法『 (hd0,5) 』才对。

    • /boot/grub2/grub.cfg 配置文件(重点在了解,不要随便改!):

    了解了 grub2 当中最麻烦的硬盘代号后,接下来,我们就可以瞧一瞧配置文件的内容了。先看一下鸟哥的 CentOS 内的 /boot/grub2/grub.cfg 好了:

    [root@study ~]# vim /boot/grub2/grub.cfg

    # 开始是 /etc/grub.d/00_header 这个脚本执行的结果展示,主要与基础配置与环境有关

    ### BEGIN /etc/grub.d/00_header ###

    set pager=1

     

    if [ -s $prefix/grubenv ]; then

      load_env

    fi

    .....(中间省略).....

    if [ x$feature_timeout_style = xy ] ; then

      set timeout_style=menu

      set timeout=5

    # Fallback normal timeout code in case the timeout_style feature is

    # unavailable.

    else

      set timeout=5

    fi

    ### END /etc/grub.d/00_header ###

     

    # 开始执行 /etc/grub.d/10_linux,主要针对实际的 Linux 核心文件的启动环境

    ### BEGIN /etc/grub.d/10_linux ###

    menuentry 'CentOS Linux 7 (Core), with Linux 3.10.0-229.el7.x86_64' --class rhel fedora \

      --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option  \

      'gnulinux-3.10.0-229.el7.x86_64-advanced-299bdc5b-de6d-486a-a0d2-375402aaab27' {

            load_video

            set gfxpayload=keep

            insmod gzio

            insmod part_gpt

            insmod xfs

            set root='hd0,gpt2'

            if [ x$feature_platform_search_hint = xy ]; then

              search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2'  94ac5f77-cb8a-495e-a65b-...

            else

              search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c

            fi

            linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro  \

                    rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet \

                    LANG=zh_TW.UTF-8

            initrd16 /initramfs-3.10.0-229.el7.x86_64.img

    }

    ### END /etc/grub.d/10_linux ###

    .....(中间省略).....

     

    ### BEGIN /etc/grub.d/30_os-prober ###

    ### END /etc/grub.d/30_os-prober ###

     

    ### BEGIN /etc/grub.d/40_custom ###

    ### END /etc/grub.d/40_custom ###

    .....(下面省略).....

    基本上,grub2 不希望你自己修改 grub.cfg 这个配置文件,取而代之的是修改几个特定的配置文件之后,由 grub2-mkconfig 这个指令来产生新的 grub.cfg 文件。 不过,你还是得要了解一下 grub2.cfg 的大致内容。

    在 grub.cfg 最开始的部份,其实大多是环境配置与默认值配置等,比较重要的当然是默认由哪个选项启动 (set default) 以及默认的秒数 (set timeout), 再来则是每一个菜单的配置,就是在『 menuentry 』这个配置值之后的项目啰!在鸟哥默认的配置文件当中,其实是有两个 menuentry 的, 也就是说,鸟哥的测试机在启动的时候应该就会有两个可以选择的菜单的意思啰!

    在 menuentry 之后会有几个项目的规范,包括『 --class, --unrestricted --id 』等等的指定项目,之后通过『 { } 』将这个菜单会用到的数据框起来, 在选择这个菜单之后就会进行括号内的动作的意思。如果真的点选了这个菜单,那 grub2 首先会加载模块,例如上表中的『 load_video, insmod gzio, insmod part_gpt, insmod xfs 』等等的项目, 都是在加载要读取核心文件所需要的磁盘、分区、文件系统、解压缩等等的驱动程序。之后就是三个比较重要的项目:

    • set root='hd0,gpt2'
      这 root 是指定 grub2 配置文件所在的那个设备。以我们的测试机来说,当初安装的时候分区出 / 与 /boot 两个设备唷,而 grub2 是在 /boot/grub2 这个位置上, 而这个位置的磁盘文件名为 /dev/vda2 ,因此完整的 grub2 磁盘名称就是 (hd0,2) 啰!因为我们的系统用的是 GPT 的磁盘分区格式, 因此全名就是『 hd0,gpt2 』!这样说,有没有听懂啊?
    • linux16 /vmlinuz-... root=/dev/mapper/centos-root ...
      这个就是 Linux 核心文件以及核心执行时所下达的参数。你应该会觉得比较怪的是,我们的核心文件不是 /boot/vmlinuz-xxx 吗? 怎么这里的配置会是在根目录呢?这个跟上面的 root 有关啦!大部分的系统大多有 /boot 这个分区,如果 /boot 没有分区, 那会是怎么回事呢?我们用下面的迭代来说明一下:
      • 如果没有 /boot 分区,仅有 / 分区:所以文件名会这样变化喔:
        /boot/vmlinuz-xxx --> (/)/boot/vmlinuz-xxx --> (hd0,msdos1)/boot/vmlinuz-xxx
      • 如果 /boot 是独立分区,则文件名的变化会是这样:
        /boot/vmlinuz-xxx --> (/boot)/vmlinuz-xxx --> (hd0,msdos1)/vmlinuz-xxx

    因此,这个 linux16 后面接的文件名得要跟上面的 root 搭配在一起,才是完整的绝对路径文件名喔!看懂了吗?至于 linux16 /vmlinuz-xxx root=/file/name 那个 root 指的是『 linux 文件系统中,根目录是在哪个设备上』的意思!启动流程中,我们就知道核心会主动去挂载根目录,并且从根目录中读取配置文件, 再进一步开始启动流程。所以,核心文件后面一定要接根目录的设备啊!这样理解吧?我们从 /etc/fstab 里面也知道根目录的挂载可以是设备文件名、 UUID 与 LABEL 名称,因此这个 root 后面也是可以带入类似 root=UUID=1111.2222.33... 之类的模式喔!

    • initrd16 /initramfs-3.10...
      这个就是 initramfs 所在的文件名,跟 linux16 那个 vmlinuz-xxx 相同,这个文件名也是需要搭配『 set root=xxx 』那个项目的设备, 才会得到正确的位置喔!注意注意!

    grub2 配置文件维护 /etc/default/grub 与 /etc/grub.d

    前一个小节我们谈到的是 grub2 的主配置文件 grub.cfg 大略的内容,但是因为该文件的内容太过复杂,数据量非常庞大,grub2 官方说明不建议我们手动修改! 而是应该要通过 /etc/default/grub 这个主要环境配置文件与 /etc/grub.d/ 目录内的相关配置文件来处理比较妥当! 我们先来聊聊 /etc/default/grub 这个主要环境配置文件好了!

    • /etc/default/grub 主要环境配置文件

    这个主配置文件的内容大概是长这样:

    [root@study ~]# cat /etc/default/grub

    GRUB_TIMEOUT=5                   # 指定默认倒数读秒的秒数

    GRUB_DEFAULT=saved               # 指定默认由哪一个菜单来启动,默认启动菜单之意

    GRUB_DISABLE_SUBMENU=true        # 是否要隐藏次菜单,通常是藏起来的好!

    GRUB_TERMINAL_OUTPUT="console"   # 指定数据输出的终端机格式,默认是通过文字终端机

    GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet"

                                     # 就是在 menuentry 括号内的 linux16 项目后续的核心参数

    GRUB_DISABLE_RECOVERY="true"     # 取消救援菜单的制作

    有兴趣的伙伴请自行 info grub 并且找到 6.1 的章节阅读一下~我们下面主要谈的是几个重要的配置项目而已。现在来说说处理的项目重点吧!

    • 倒数时间参数: GRUB_TIMEOUT

    这个配置值相当简单,后面就是接你要倒数的秒数即可~例如要等待 30 秒,就在这边改成『GRUB_TIMEOUT=30』即可!如果不想等待则输入 0 , 如果一定要使用者选择,则填 -1 即可!

    • 是否隐藏菜单项目:GRUB_TIMEOUT_STYLE

    这个项目可选择的配置值有 menu, countdown, hidden 等等。如果没有配置,默认是 menu 的意思。这个项目主要是在配置要不要显示菜单! 如果你不想要让使用者看到菜单,这里可以配置为 countdown!那 countdown 与 hidden 有啥差异呢?countdown 会在屏幕上显示剩余的等待秒数, 而 hidden 则空空如也~除非你有特定的需求,否则这里一般鸟哥建议配置为 menu 较佳啦!

    • 信息输出的终端机模式:GRUB_TERMINAL_OUTPUT

    这个项目是指定输出的画面应该使用哪一个终端机来显示的意思,主要的配置值有『 console, serial, gfxterm, vga_text 』等等。 除非有特别的需求,否则一般使用 console 即可!

    • 默认启动菜单项目:GRUB_DEFAULT

    这个项目在指定要用哪一个菜单 (menuentry) 来作为默认启动项目的意思。能使用的配置值包括有『 saved, 数字, title 名, ID 名』等等。 假设你有三笔 menuentry 的项目大约像这样:

    menuentry '1st linux system' --id 1st-linux-system { ...}

    menuentry '2nd linux system' --id 2nd-linux-system { ...}

    menuentry '3rd win system' --id 3rd-win-system { ...}

    几个常见的配置值是这样的:

    [root@study ~]#

    GRUB_DEFAULT=1

        代表使用第二个 menuentry 启动,因为数字的编号是以 0 号开始编的!

     

    GRUB_DEFAULT=3rd-win-system

        代表使用第三个 menuentry 启动,因为里头代表的是 ID 的项目!它会找到 --id 喔!

     

    GRUB_DEFAULT=saved

        代表使用 grub2-set-default 来配置哪一个 menuentry 为默认值的意思。通常默认为 0

    一般来说,默认就是以第一个启动菜单来作为默认项目,如果想要有不同的菜单配置,可以在这个项目填选所需要的 --id 即可。 当然啦,你的 id 就应该不要重复啰!

    • 核心的外加参数功能:GRUB_CMDLINE_LINUX

    如果你的核心在启动的时候还需要加入额外的参数,就在这里加入吧!举例来说,如果你除了默认的核心参数之外,还需要让你的磁盘读写机制为 deadline 这个机制时, 可以这样处理:

    GRUB_CMDLINE_LINUX="..... crashkernel=auto rhgb quiet elevator=deadline"

    在既有的项目之后加上如同上表的配置,这样就可以在启动时额外的加入磁盘读写的机制项目配置了!

    这个主要环境配置文件编写完毕之后,必须要使用 grub2-mkconfig 来重建 grub.cfg 才行喔!因为主配置文件就是 grub.cfg 而已, 我们是通过许多脚本的协力来完成 grub.cfg 的自动创建。当然啰,额外自己配置的项目,就是写入 /etc/default/grub 文件内就是了。 我们来测试一下下面调整项目,看看你会不会修订主要环境配置文件了呢?

    问:

    假设你需要 (1)启动菜单等待 40 秒钟、 (2)默认用第一个菜单启动、 (3)菜单请显示出来不要隐藏、 (4)核心外带『elevator=deadline』的参数值, 那应该要如何处理 grub.cfg 呢?

    答:

    直接编辑主要环境配置文件后,再以 grub2-mkconfig 来重建 grub.cfg 喔!

    # 1. 先编辑主要环境配置文件:

    [root@study ~]# vim /etc/default/grub

    GRUB_TIMEOUT=40

    GRUB_DEFAULT=0

    GRUB_TIMEOUT_STYLE=menu

    GRUB_DISABLE_SUBMENU=true

    GRUB_TERMINAL_OUTPUT="console"

    GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet elevator=deadline"

    GRUB_DISABLE_RECOVERY="true"

     

    # 2. 开始重新建置 grub.cfg !

    [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg

    Generating grub configuration file ...

    Found linux image: /boot/vmlinuz-3.10.0-229.el7.x86_64

    Found initrd image: /boot/initramfs-3.10.0-229.el7.x86_64.img

    Found linux image: /boot/vmlinuz-0-rescue-309eb890d09f440681f596543d95ec7a

    Found initrd image: /boot/initramfs-0-rescue-309eb890d09f440681f596543d95ec7a.img

    done

     

    # 3. 检查看看 grub.cfg 的内容是否真的是改变了?

    [root@study ~]# grep timeout /boot/grub2/grub.cfg

      set timeout_style=menu

      set timeout=40

     

    [root@study ~]# grep default /boot/grub2/grub.cfg

       set default="0"

     

    [root@study ~]# grep linux16 /boot/grub2/grub.cfg

            linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/.... elevator=deadline

            linux16 /vmlinuz-0-rescue-309eb890d09f440681f5965.... elevator=deadline

    • 菜单创建的脚本 /etc/grub.d/*

    你应该会觉得很奇怪, grub2-mkconfig 执行之后,屏幕怎么会主动的去抓到 linux 的核心,还能够找到对应核心版本的 initramfs 呢? 怎么这么厉害?其实 grub2-mkconfig 会去分析 /etc/grub.d/* 里面的文件,然后执行该文件来创建 grub.cfg 的啦! 所以啰, /etc/grub.d/* 里面的文件就显得很重要了。一般来说,该目录下会有这些文件存在:

    • 00_header:主要在建立初始的显示项目,包括需要加载的模块分析、屏幕终端机的格式、倒数秒数、菜单是否需要隐藏等等,大部分在 /etc/default/grub 里面所配置的变量,大概都会在这个脚本当中被利用来重建 grub.cfg 。
    • 10_linux:根据分析 /boot 下面的文件,尝试找到正确的 linux 核心与读取这个核心需要的文件系统模块与参数等,都在这个脚本运作后找到并配置到 grub.cfg 当中。 因为这个脚本会将所有在 /boot 下面的每一个核心文件都对应到一个菜单,因此核心文件数量越多,你的启动菜单项目就越多了。如果未来你不想要旧的核心出现在菜单上,那可以通过移除旧核心来处理即可。
    • 30_os-prober:这个脚本默认会到系统上找其他的 partition 里面可能含有的操作系统,然后将该操作系统做成菜单来处理就是了。 如果你不想要让其他的操作系统被检测到并拿来启动,那可以在 /etc/default/grub 里面加上『 GRUB_DISABLE_OS_PROBER=true 』取消这个文件的运行。
    • 40_custom:如果你还有其他想要自己手动加上去的菜单项目,或者是其他的需求,那么建议在这里补充即可!

    所以,一般来说,我们会修改的就是仅有 40_custom 这个文件即可。那这个文件内容也大多在放置管理员自己想要加进来的菜单项目就是了。好了,那问题来了,我们知道 menuentry 就是一个菜单,那后续的项目有哪些东西呢?简单的说,就是这个 menuentry 有几种常见的配置? 亦即是 menuentry 的功能啦!常见的有这几样:

    • 直接指定核心启动

    基本上如果是 Linux 的核心要直接被用来启动,那么你应该要通过 grub2-mkconfig 去抓 10_linux 这个脚本直接制作即可,因此这个部分你不太需要记忆! 因为在 grub.cfg 当中就已经是系统能够捉到的正确的核心启动菜单了!不过如果你有比较特别的参数需要进行呢?这时候你可以这样作: (1)先到 grub.cfg 当中取得你要制作的那个核心的菜单项目,然后将它复制到 40_custom 当中 (2)再到 40_custom 当中依据你的需求修改即可。

    这么说或许你很纳闷,我们来做个实际练习好了:

    问:

    如果你想要使用第一个原有的 menuentry 取出来后,增加一个菜单,该菜单可以强制 systemd 使用 graphical.target 来启动 Linux 系统, 让该菜单一定可以使用图形界面而不用理会 default.target 的链接,该如何设计?

    答:

    当核心外带参数中,有个『 systemd.unit=??? 』的外带参数可以指定特定的 target 启动!因此我们先到 grub.cfg 当中,去复制第一个 menuentry , 然后进行如下的配置:

    [root@study ~]# vim /etc/grub.d/40_custom

    menuentry 'My graphical CentOS, with Linux 3.10.0-229.el7.x86_64' --class rhel fedora

              --class gnu-linux --class gnu --class os --unrestricted --id 'mygraphical' {

            load_video

            set gfxpayload=keep

            insmod gzio

            insmod part_gpt

            insmod xfs

            set root='hd0,gpt2'

            if [ x$feature_platform_search_hint = xy ]; then

              search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2'  94ac5f77-cb8a-495e-a65b-...

            else

              search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c

            fi

            linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=

                    centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet

                    elevator=deadline systemd.unit=graphical.target

            initrd16 /initramfs-3.10.0-229.el7.x86_64.img

    }

    # 请注意,上面的资料都是从 grub.cfg 里面复制过来的,增加的项目仅有特殊字体的部分而已!

    # 同时考虑画面宽度,该项目稍微被变动过,请依据您的环境来配置喔!

     

    [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg

    当你再次 reboot 时,系统就会多出一个菜单给你选择了!而且选择该菜单之后,你的系统就可以直接进入图形界面 (如果有安装相关的 X window 软件时), 而不必考虑 default.target 是啥东西了!了解乎?

    • 通过 chainloader 的方式移交 loader 控制权

    所谓的 chain loader (启动管理程序的链结) 仅是在将控制权交给下一个 boot loader 而已, 所以 grub2 并不需要认识与找出 kernel 的文件名 ,『 他只是将 boot 的控制权交给下一个 boot sector 或 MBR 内的 boot loader 而已 』 所以通常他也不需要去查验下一个 boot loader 的文件系统!

    一般来说, chain loader 的配置只要两个就够了,一个是预计要前往的 boot sector 所在的分区代号, 另一个则是配置 chainloader 在那个分区的 boot sector (第一个扇区) 上!假设我的 Windows 分区在 /dev/sda1 ,且我又只有一颗硬盘,那么要 grub 将控制权交给 windows 的 loader 只要这样就够了:

    menuentry "Windows" {

            insmod chain      # 你得要先加载 chainloader 的模块对吧?

            insmod ntfs       # 建议加入 windows 所在的文件系统模块较佳!

            set root=(hd0,1)  # 是在哪一个分区~最重要的项目!

            chainloader +1    # 请去 boot sector 将 loader 软件读出来的意思!

    }

    通过这个项目我们就可以让 grub2 交出控制权了!

    问:

    假设你的测试系统上面使用 MBR 分区,并且出现如下的数据:

    [root@study ~]# fdisk -l /dev/vda

       Device Boot      Start         End      Blocks   Id  System

    /dev/vda1            2048    10487807     5242880   83  Linux

    /dev/vda2   *    10487808   178259967    83886080    7  HPFS/NTFS/exFAT

    /dev/vda3       178259968   241174527    31457280   83  Linux

    其中 /dev/vda2 使用是 windows 7 的操作系统。现在我需要增加两个启动选项,一个是取得 windows 7 的启动菜单,一个是回到 MBR 的默认环境,应该如何处理呢?

    答:

    windows 7 在 /dev/vda2 亦即是 hd0,msdos2 这个地方,而 MBR 则是 hd0 即可,不需要加上分区啊!因此整个配置会变这样:

    [root@study ~]# vim /etc/grub.d/40_custom

    menuentry 'Go to Windows 7' --id 'win7' {

            insmod chain

            insmod ntfs

            set root=(hd0,msdos2)

            chainloader +1

    }

    menuentry 'Go to MBR' --id 'mbr' {

            insmod chain

            set root=(hd0)

            chainloader +1

    }

     

    [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg

    另外,如果每次都想要让 windows 变成默认的启动选项,那么在 /etc/default/grub 当中配置好『 GRUB_DEFAULT=win7 』 然后再次 grub2-mkconfig 这样即可啦!不要去算 menuentry 的顺序喔!通过 --id 内容来处理即可!

    initramfs 的重要性与建立新 initramfs 文件

    他的目的在于提供启动过程中所需要的最重要核心模块,以让系统启动过程可以顺利完成。会需要 initramfs 的原因,是因为核心模块放置于 /lib/modules/$(uname -r)/kernel/ 当中, 这些模块必须要根目录 (/) 被挂载时才能够被读取。但是如果核心本身不具备磁盘的驱动程序时, 当然无法挂载根目录,也就没有办法取得驱动程序,因此造成两难的地步。

    initramfs 可以将 /lib/modules/.... 内的『启动过程当中一定需要的模块』包成一个文件 (文件名就是 initramfs), 然后在启动时通过主机的 INT 13 硬件功能将该文件读出来解压缩,并且 initramfs 在内存内会仿真成为根目录, 由于此虚拟文件系统 (Initial RAM Disk) 主要包含磁盘与文件系统的模块,因此我们的核心最后就能够认识实际的磁盘, 那就能够进行实际根目录的挂载啦!所以说:『initramfs 内所包含的模块大多是与启动过程有关,而主要以文件系统及硬盘模块 (如 usb, SCSI 等) 为主』的啦!

    一般来说,需要 initramfs 的时刻为:

    • 根目录所在磁盘为 SATA、USB 或 SCSI 等连接接口;
    • 根目录所在文件系统为 LVM, RAID 等特殊格式;
    • 根目录所在文件系统为非传统 Linux 认识的文件系统时;
    • 其他必须要在核心加载时提供的模块。

    Tips

    之前鸟哥忽略 initrd 这个文件的重要性,是因为鸟哥很穷。因为鸟哥的 Linux 主机都是较早期的硬件, 使用的是 IDE 接口的硬盘,而且并没有使用 LVM 等特殊格式的文件系统,而 Linux 核心本身就认识 IDE 接口的磁盘, 因此不需要 initramfs 也可以顺利启动完成的。自从 SATA 硬盘流行起来后,没有 initramfs 就没办法启动了! 因为 SATA 硬盘使用的是 SCSI 模块来驱动的,而 Linux 默认将 SCSI 功能编译成为模块....

    一般来说,各 distribution 提供的核心都会附上 initramfs 文件,但如果妳有特殊需要所以想重制 initramfs 文件的话, 可以使用 dracut / mkinitrd 来处理的。这个文件的处理方式很简单, man dracut 或 man mkinitrd 就知道了! CentOS 7 应该要使用 dracut 才对,不过 mkinitrd 还是有保留下来,两者随便你玩!鸟哥这里主要是介绍 dracut 就是了!

    [root@study ~]# dracut [-fv] [--add-drivers 列表] initramfs文件名 核心版本

    选项与参数:

    -f   :强迫编译出 initramfs ,如果 initramfs 文件已经存在,则覆盖掉旧文件

    -v   :显示 dracut 的运行过程

    --add-drivers 列表:在原本的默认核心模块中,增加某些你想要的模块!模块位于核心所在目录

                        /lib/modules/$(uname -r)/kernel/*

    initramfs文件名     :就是你需要的文件名!开头最好就是 initramfs,后面接版本与功能

    核心版本          :默认当然是目前运行中的核心版本,不过你也可以手动输入其他不同版本!

    其实 dracut 还有很多功能,例如下面的几个参数也可以参考看看:

    --modules  :将 dracut 所提供的启动所需模块 (核心核模块) 加载,可用模块在下面的目录内

                 /usr/lib/dracut/modules.d/

    --gzip|--bzip2|--xz:尝试使用哪一种压缩方式来进行 initramfs 压缩。默认使用 gzip 喔!

    --filesystems :加入某些额外的文件系统支持!

     

    例一:以 dracut 的默认功能建立一个 initramfs 虚拟磁盘文件

    [root@study ~]# dracut -v initramfs-test.img $(uname -r)

    Executing: /sbin/dracut -v initramfs-test.img 3.10.0-229.el7.x86_64

    *** Including module: bash ***                     # 先加载 dracut 本身的模块支持

    *** Including module: nss-softokn ***

    *** Including modules done ***

    .....(中间省略)..... # 下面两行在处理核心模块

    *** Installing kernel module dependencies and firmware ***

    *** Installing kernel module dependencies and firmware done ***

    .....(中间省略).....

    *** Generating early-microcode cpio image ***      # 建立微指令集

    *** Constructing GenuineIntel.bin ****

    *** Store current command line parameters ***

    *** Creating image file ***                        # 开始建立 initramfs 啰!

    *** Creating image file done ***

     

    例二:额外加入 e1000e 网卡驱动与 ext4/nfs 文件系统在新的 initramfs 内

    [root@study ~]# dracut -v --add-drivers "e1000e" --filesystems "ext4 nfs" \

    >  initramfs-new.img $(uname -r)

    [root@study ~]# lsinitrd initramfs-new.img  | grep -E '(e1000|ext4|nfs)'

     usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e

     usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko

     usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4

     usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4/ext4.ko

     usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs

     usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs/nfs.ko

    # 你可以看得到,新增的模块现在正在新的 initramfs 当中了呢!很愉快喔!

    initramfs 建立完成之后,同时核心也处理完毕后,我们就可以使用 grub2 来建立菜单了!下面继续瞧一瞧吧!

    测试与安装 grub2

    如果你的 Linux 主机本来就是使用 grub2 作为 loader 的话,那么你就不需要重新安装 grub2 了, 因为 grub2 本来就会主动去读取配置文件啊!您说是吧!但如果你的 Linux 原来使用的并非 grub2 , 那么就需要来安装啦!如何安装呢?首先,你必须要使用 grub-install 将一些必要的文件复制到 /boot/grub2 里面去,你应该这样做的:

    [root@study ~]# grub2-install [--boot-directory=DIR] INSTALL_DEVICE

    选项与参数:

    --boot-directory=DIR 那个 DIR 为实际的目录,使用 grub2-install 默认会将grub2 所有的文件都复制到 /boot/grub2/* ,如果想要复制到其他目录与设备去,就得要用这个参数。

    INSTALL_DEVICE 安装的设备代号啦!

     

    例一:将 grub2 安装在目前系统的 MBR 下面,我的系统为 /dev/vda:

    [root@study ~]# grub2-install /dev/vda

    # 因为原本 /dev/vda 就是使用 grub2 ,所以似乎不会出现什么特别的信息。

    # 如果去查阅一下 /boot/grub2 的内容,会发现所有的文件都更新了,因为我们重装了!

    # 但是注意到,我们并没有配置文件喔!那要自己建立!

    基本上,grub2-install 大概仅能安装 grub2 主程序与相关软件到 /boot/grub2/ 那个目录去,如果后面的设备填的是整个系统 (/dev/vda, /dev/sda...), 那 loader 的程序才会写入到 MBR 里面去。如果是 XFS 文件系统的 /dev/vda2 设备的话 (个别 partition),那 grub2-install 就会告诉你, 该文件系统并不支持 grub2 的安装喔!也就是你不能用 grub2-install 将你的主程序写入到 boot sector 里头去的意思啦! 那怎办?没关系,来强迫写入一下看看!

    # 尝试看一下你的系统中有没有其他的 xfs 文件系统,且为传统的 partition 类型?

    [root@study ~]# df -T |grep -i xfs

    /dev/mapper/centos-root   xfs       10475520 4128728   6346792  40% /

    /dev/mapper/centos-home   xfs        5232640  665544   4567096  13% /home

    /dev/mapper/raidvg-raidlv xfs        1558528   33056   1525472   3% /srv/raidlvm

    /dev/vda2                 xfs        1038336  144152    894184  14% /boot

    /dev/vda4                 xfs        1038336   63088    975248   7% /srv/myproject

    # 看起来仅有 /dev/vda4 比较适合做个练习的模样了!来瞧瞧先!

     

    # 将 grub2 的主程序安装到 /dev/vda4 去看看!

    [root@study ~]# grub2-install /dev/vda4

    Installing for i386-pc platform.

    grub2-install: error: hostdisk//dev/vda appears to contain a xfs filesystem which isn't known to reserve space for DOS-style boot.  Installing GRUB there could result in FILESYSTEM DESTRUCTION if valuable data is overwritten by grub-setup (--skip-fs-probe disables this check, use at your own risk).

    # 说是 xfs 恐怕不能支持你的 boot sector 概念!这个应该是误判!所以我们还是给它强制装一下!

     

    [root@study ~]# grub2-install --skip-fs-probe /dev/vda4

    Installing for i386-pc platform.

    grub2-install: warning: File system ‘xfs’ doesn't support embedding.

    grub2-install: warning: Embedding is not possible.  GRUB can only be installed in this setup by using blocklists.  However, blocklists are UNRELIABLE and their use is discouraged..

    grub2-install: error: will not proceed with blocklists.

    # 还是失败!因为还是担心 xfs 被搞死~好!没问题!加个 --force 与 --recheck 重新处理一遍!

     

    [root@study ~]# grub2-install --force --recheck --skip-fs-probe /dev/vda4

    Installing for i386-pc platform.

    grub2-install: warning: File system ‘xfs’ doesn't support embedding.

    grub2-install: warning: Embedding is not possible.  GRUB can only be installed in this setup by using blocklists.  However, blocklists are UNRELIABLE and their use is discouraged..

    Installation finished. No error reported.

    # 注意看!原本是无法安装的错误,现在仅有 warning 警告信息,所以这样就安装到 partition 上了!

    上面这样就将 grub2 的主程序安装到 /dev/vda4 以及重新安装到 MBR 里面去了。现在来思考一下,我们知道 grub2 主程序会去找 grub.cfg 这个文件,大多是在 /boot/grub2/grub.cfg 里面,那有趣了,我们的 MBR 与 /dev/vda4 都是到 /boot/grub2/grub.cfg 去抓配置吗? 如果是多重操作系统那怎办?呵呵!这就需要重新进入新系统才能够安装啦!举个例子来说啰:

    问:

    假设你的测试系统上面使用 MBR 分区,并且出现如下的数据:

    [root@study ~]# fdisk -l /dev/vda

       Device Boot      Start         End      Blocks   Id  System

    /dev/vda1            2048    10487807     5242880   83  Linux

    /dev/vda2   *    10487808   178259967    83886080    7  HPFS/NTFS/exFAT

    /dev/vda3       178259968   241174527    31457280   83  Linux

    其中 /dev/vda1, /dev/vda3 是两个 CentOS 7 系统,而 /dev/vda2 则是 windows 7 系统。安装的流程是依序 /dev/vda1 --> /dev/vda2 --> /dev/vda3。因此,安装好而且重新启动后,系统其实是默认进入 /dev/vda3 这个 CentOS 7 的系统的。 此时 MBR 会去读取的配置文件在 (/dev/vda3)/boot/grub2/grub.cfg 才对。

    因为 /dev/vda1 应该是用来管理启动菜单的,而 /dev/vda2 及 /dev/vda3 在规划中就是用来让学生操作的,因此默认情况下, /dev/vda1 内的 CentOS 系统应该只会在启动的时候用到而已,或者是出问题时会找他来使用。至于 /dev/vda3 及 /dev/vda2 则可能因为学生的误用, 因此未来可能会升级或删除或重灌等。那妳如何让系统永远都是使用 /dev/vda1 启动呢?

    答:

    因为 MBR 的 boot loader 应该要去 (/dev/vda1)/boot/grub2/grub.cfg 读取相关配置才是正常的!所以,你可以使用几种基本的方式来处理:

    • 因为 CentOS 7 会主动找到其他操作系统,因此你可以在 /dev/vda3 的启动菜单中找到 /dev/vda1 的启动选项,请用该选项进入系统, 你就能够进入 /dev/vda1 了!
    • 假设没能抓到 /dev/vda1 ,那妳可以在 /dev/vda3 下面使用 chroot 来进入 /dev/vda1 喔!
    • 使用救援光盘去抓到正确的 /dev/vda1,然后取得 /dev/vda1 的系统喔!

    等到进入系统后,修改 /etc/default/grub 及 /etc/grub.d/40_custom 之后,使用 grub2-mkconfig -o /boot/grub2/grub.cfg , 然后重新 grub2-install /dev/vda 就能够让你的 MBR 去取得 /dev/vda1 内的配置文件啰!

     

    问:

    我们的测试机目前为 40 秒倒数,且有一个强制进入图形界面的『 My graphical CentOS7 』菜单! 现在我们想要多加两个菜单,一个是回到 MBR 的 chainloader,一个是使用 /dev/vda4 的 chainloader,该如何处理?

    答:

    因为没有必要重新安装 grub2 ,直接修改即可。修改 40_custom 成为这样:

    [root@study ~]# vim /etc/grub.d/40_custom

    # 最下面加入这两个项目即可!

    menuentry 'Goto MBR' {

            insmod chain

            insmod part_gpt

            set root=(hd0)

            chainloader +1

    }

    menuentry 'Goto /dev/vda4' {

            insmod chain

            insmod part_gpt

            set root=(hd0.gpt4)

            chainloader +1

    }

     

    [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg

    最后总结一下:

    1. 如果是从其他 boot loader 转成 grub2 时,得先使用 grub2-install 安装 grub2 配置文件;
    2. 承上,如果安装到 partition 时,可能需要加上额外的许多参数才能够顺利安装上去!
    3. 开始编辑 /etc/default/grub 及 /etc/grub.d/* 这几个重要的配置文件;
    4. 使用 grub2-mkconfig -o /boot/grub2/grub.cfg 来建立启动的配置文件!

    启动前的额外功能修改

    事实上,前几个小节配置好之后,你的 grub2 就已经在你的 Linux 系统上面了,而且同时存在于 MBR 与 boot sector 当中呢!所以,我们已经可以重新启动来查阅看看啦! 另外,如果你正在进行启动,那么请注意,我们可以在默认菜单 (鸟哥的范例当中是 40 秒) 按下任意键, 还可以进行 grub2 的『在线编修』功能喔!真是棒啊!先来看看启动画面吧!

    grub2 启动画面示意图

    由于默认菜单就没有隐藏,因此你会直接看到这 5 个菜单而已,同时会有读秒的咚咚在倒数。 菜单部分的画面其实就是 menuentry 后面的文字啦!你现在知道如何修改 menuentry 后面的文字了吧!。 然后如果你点选了『Goto MBR』与『Goto /dev/vda4』时,怪了!怎么发现到菜单又重新回来了呢? 这是因为这两个 Goto 的菜单都是重新读取主配置文件,而 MBR 与 /dev/vda4 配置文件的读取都是来自 (/dev/vda2)/boot/grub2/grub.cfg 的缘故! 因此这个画面就会重复出现了!这样了解乎?

    另外,如果你再仔细看的话,会发现到上图中底部还有一些细部的选项,似乎有个 'e' edit 的样子! 没错~ grub2 支持在线编修指令喔!这是个很有用的功能!假如刚刚你将 grub.cfg 的内容写错了,导致出现无法启动的问题时, 我们可以查阅该 menuentry 菜单的内容并加以修改喔!举例来说,我想要知道第一个菜单的实际内容时,将反白光棒移动到第一个菜单, 再按下 'e' 会进入如下画面:

    grub2 额外的指令编辑模式

    因为 CentOS 7 默认没有提供美美的底图给我们使用,因此这里会看到无法分辨的两个区块!事实上它真的是两个区块, 上方是实际你可以编辑的内容区段,仔细看,这不就是我们在 grub.cfg 里面配置的东西吗?没错!此时你还可以继续进一步修改喔! 用上/下/左/右按键到你想要编辑的地方,直接删除、新增即可!

    至于下方画面则仅是一些编辑说明,重点在告诉你,编辑完毕之后,若想要取消而回到前一个画面,请使用 [ctrl]+c 或者是 [esc] 回去, 若是修改完毕,想要直接启动时,请使用 [ctrl]+x 来启动啰!

    问:

    现在我想要让系统启动的过程中,让这个系统进入救援模式 (rescue) ,而不想要进入系统后使用 systemctl rescue 时,该如何处理?

    答:

    按下『向下』的箭头键,直到出现 linux16 那一行,然后在那一行的最后面加上 systemd.unit=rescue.target , 画面有点像这样:

    然后再按下 [ctrl]+x 来进入系统,就能够取得 rescue 的环境了!登入后有点像这样:

    接着下来你就可以开始救援系统啰!

    你可能会觉得很讶异!早期 System V 的系统中,进入 runlevel 1 的状态是不需要输入 root 密码的,在 systemd 的年代,哇!! 竟然需要密码才能够进入救援模式耶!而且是强制要有 root 密码耶!如果你是 root 密码忘记要救援,救个鬼啊~还是需要 root 密码啊! 那怎办?没关系~本章稍后会告诉你应该要如何处理的啦!

    关于启动画面与终端机画面的图形显示方式

    如果你想要让你的启动画面使用图形显示方式,例如使用中文来显示你的画面啊!因为我们默认的 locale 语言就是 zh_TW.utf8 嘛! 所以理论上 grub2 会显是中文出来才对啊!有没有办法达成呢?是有的~通过图形显是的方法即可!不过, 我们得要重新修改 grub.cfg 才行喔!依据下面的方式来处理:

    # 先改重要的配置文件

    [root@study ~]# vim /etc/default/grub

    .....(前面省略).....

    GRUB_TERMINAL=gfxterm       # 配置主要的终端机显示为图形界面!

    GRUB_GFXMODE=1024x768x24    # 图形界面的 X, Y, 彩度资料

    GRUB_GFXPAYLOAD_LINUX=keep  # 保留图形界面,不要使用 text 喔!

     

    # 重新建立配置文件

    [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg

    再次的重新启动,这时你会看到有点像下面的模样的画面喔!

    使用图形显示模式的启动画面

    看到没有?上图中有繁体中文喔!中文喔喔喔喔喔喔~真是开心啊! 未来如果你有需要在你的启动菜单当中加入许多属于你自己的公司/企业的画面,那就太容易啰! ^_^

    为个别菜单加上密码

    想象一个环境,如果你管理的是一间计算机教室,这间计算机教室因为可对外开放,但是你又担心某些 partition 被学生不小心的弄乱,因此你可能会想要将某些启动菜单作个保护。这个时候,为每个菜单作个加密的密码就是个可行的方案啦!

    另外,从启动过程中,你会知道使用者可以在启动的过程中于 grub2 内选择进入某个菜单,以及进入 grub2 指令模式去修改菜单的参数数据等。 也就是说,主要的 grub2 控制有: (1)grub2 的菜单指令列修改与 (2)进入选择的菜单启动流程。好了,如刚刚谈到的计算机教室案例, 你要怎么让某些密码可以完整的掌控 grub2 的所有功能,某些密码则只能进入个别的菜单启动呢?这就得要牵涉到 grub2 的账号机制了!

    • grub2 的账号、密码与菜单配置

    grub2 有点在模拟 Linux 的账号管理方案喔!因为在 grub2 的菜单管理中,有针对两种身份进行密码配置:

    • superusers: 配置系统管理员与相关参数还有密码等,使用这个密码的用户,将可在 grub2 内具有所有修改的权限。 但一旦配置了这个 superusers 的参数,则所有的指令修改将会被变成受限制的!
    • users: 配置一般账号的相关参数与密码,可以配置多个用户喔!使用这个密码的用户可以选择要进入某些菜单项目。 不过,菜单项目也得要搭配相对的账号才行喔!(一般来说,使用这种密码的账号并不能修改菜单的内容,仅能选择进入菜单去启动而已)

    这样说可能你不是很容易看得懂,我们使用下面的一个范例来说明你就知道怎么处理了。另外,下面的范例是单纯给读者们看看而已的~ 不能够直接用在我们的测试机器里面喔!

    问:

    假设你的系统有三个各别的操作系统,分别安装在 (hd0,1), (hd0,2), (hd0,3) 当中。假设 (hd0,1) 是所有人都可以选择进入的系统, (hd0,2) 是只有系统管理员可以进入的系统,(hd0,3)则是另一个一般用户与系统管理员可以进入的系统。另外,假设系统管理员的账号/密码配置为 vbird/abcd1234, 而一般账号为 dmtsai/dcba4321 ,那该如何配置?

    答:

    如果依据上述的说明,其实没有用到 Linux 的 linux16 与 initrd16 的项目,只需要 chainloader 的项目而已! 因此,整个 grub.cfg 会有点像下面这样喔:

    # 第一个部分是先配置好管理员与一般账号的账号名称与密码项目!

     

    set superusers="vbird"    # 这里是配置系统管理员的账号名称为啥的意思!

    password vbird abcd1234   # 当然要给予这个账号密码啊!

    password dmtsai dcba4321  # 没有输入 superuses 的其他账号,当然就是判定为一般账号

     

    menuentry "大家都可以选择我来启动喔!" --unrestricted {

            set root=(hd0,1)

            chainloader +1

    }

     

    menuentry "只有管理员的密码才有办法使用" --users "" {

            set root=(hd0,2)

            chainloader +1

    }

     

    menuentry "只有管理员与 dmtsai 才有办法使用喔!" --users dmtsai {

            set root=(hd0,3)

            chainloader +1

    }

    如上表所示,你得要使用 superuses 来指定哪个账号是管理员!另外,这个账号与 Linux 的实体账号无关,这仅是用来判断密码所代表的意义而已。 而密码的给予有两种语法:

    • password_pbkdf2 账号 『使用grub2-mkpasswd-pbkdf2所产生的密码』
    • password 账号 『没加密的明码』

    有了账号与密码之后,在来就是在个别的菜单上面加上是否要取消限制 (--unrestricted) 或者是给予哪个用户 (--users) 的配置项目。 同时请注意喔,所有的系统管理员所属的密码应该是能够修改所有的菜单,因此你无须在第三个菜单上面加入 vbird 这个管理员账号! 这样说你就可以了解了吧?

    你很可能会这样说:『了解个头啦!怎么可能会了解!前面不是才说过:「不要手动去修改 grub.cfg 」吗?这里怎么直接列出 grub.cfg 的内容? 上面这些项目我是要在哪些环境配置文件里面修改啦?』呵呵~您真内行,没有被骗耶~好厉害~好厉害!

    • grub2 密码配置的文件位置与加密的密码

    还记得我们在前几小节谈到主要的环境配置是在 /etc/grub.d/* 里面吧?里面的文件文件名有用数字开头,那些数字照顺序,就是 grub.cfg 的来源顺序了。 因此最早被读的应该是 00_header,但是那个文件的内容挺重要的,所以 CentOS 7 不建议你改它~那要改谁?就自己建立一个名为 01_users 的文件即可! 要注意是两个数字开头接着底线的文件名才行喔!然后将账号与密码参数给它补进去!

    现在让我们将 vbird 与 dmtsai 的密码加密,实际在我们的测试机器上面创建起来吧!

    # 1. 先取得 vbird 与 dmtsai 的密码。下面我仅以 vbird 来说明而已!

    [root@study ~]# grub2-mkpasswd-pbkdf2

    Enter password:    # 这里输入你的密码

    Reenter password:  # 再一次输入密码

    PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.9A2EBF7A1F484...

    # 上面特殊字体从 grub.pbkdf2.... 的那一行,全部的数据就是你的密码喔!复制下来!

     

    # 2. 将密码与账号写入到 01_users 文件内

    [root@study ~]# vim /etc/grub.d/01_users

    cat << eof

    set superusers="vbird"

    password_pbkdf2 vbird grub.pbkdf2.sha512.10000.9A2EBF7A1F484904FF3681F97AE22D58DFBFE65A...

    password_pbkdf2 dmtsai grub.pbkdf2.sha512.10000.B59584C33BC12F3C9DB8B18BE9F557631473AED...

    eof

    # 请特别注意,在 /etc/grub.d/* 下面的文件是『执行脚本』文件,是要被执行的!

    # 因此不能直接写帐密,而是通过 cat 或 echo 等指令方式来将帐密数据显示出来才行喔!

     

    # 3. 因为 /etc/grub.d/ 下面应该是执行文件,所以刚刚建立的 01_users 当然要给予执行权限

    [root@study ~]# chmod a+x /etc/grub.d/01_users

    [root@study ~]# ll /etc/grub.d/01_users

    -rwxr-xr-x. 1 root root 649 Aug 31 19:42 /etc/grub.d/01_users

    很快的,你就已经将密码创建妥当了!接下来就来聊一聊,那么每个 menuentry 要如何修改呢?

    • 为个别的菜单配置账号密码的使用模式

    回想一下我们之前的配置,目前测试机器的 Linux 系统菜单应该有五个:

    • 来自 /etc/grub.d/10_linux 这个文件主动检测的两个 menuentry;
    • 来自 /etc/grub.d/40_custom 这个我们自己配置的三个 menuentry

    在 40_custom 内的配置,我们可以针对每个 menuentry 去调整,而且该调整是固定的,不会随便被更改。至于 10_linux 文件中, 则每个 menuentry 的配置都会依据 10_linux 的数据去变更,也就是由 10_linux 检测到的核心启动菜单都会是相同的意思。

    因为我们已经在 01_users 文件内配置了 set superusers="vbird" 这个配置值,因此每个菜单内的参数除了知道 vbird 密码的人之外, 已经不能随便修改了喔!所以,选择 10_linux 制作出来的菜单启动,应该就算正常启动,所以,我们默认不要使用密码好了! 刚刚好 10_linux 的 menuentry 配置值就是这样:

    [root@study ~]# vim /etc/grub.d/10_linux

    .....(前面省略).....

    CLASS="--class gnu-linux --class gnu --class os --unrestricted"

    # 这一行大约在 29 行左右,你可以利用 unrestricted 去搜寻即可!

    # 默认已经不受限制 (--unrestricted) 了!如果想要受限制,在这里将 --unrestricted

    # 改成你要使用的 --users "账号名称" 即可!不过,还是不建议修改啦!

    现在我们假设在 40_custom 里面要增加一个可以进入救援模式 (rescue) 的环境,并且放置到最后一个菜单中,同时仅有知道 dmtsai 的密码者才能够使用, 那你应该这样作:

    [root@study ~]# vim /etc/grub.d/40_custom

    .....(前面省略).....

    menuentry 'Rescue CentOS7, with Linux 3.10.0-229.el7.x86_64' --users dmtsai {

            load_video

            set gfxpayload=keep

            insmod gzio

            insmod part_gpt

            insmod xfs

            set root='hd0,gpt2'

            if [ x$feature_platform_search_hint = xy ]; then

              search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2'  94ac5f77-cb8a-...

            else

              search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c

            fi

            linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv

                =centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet

                systemd.unit=rescue.target

            initrd16 /initramfs-3.10.0-229.el7.x86_64.img

    }

     

    [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg

    最后一步当然不要忘记重建你的 grub.cfg 啰!然后重新启动测试一下,如果一切顺利,你会发现如下的画面:

    默认的菜单环境

    你直接在 1, 2, 3 菜单上面按下 enter 就可以顺利的继续启动,而不用输入任何的密码,这是因为有 --unrestricted 参数的关系。 第 4, 5 菜单中,如果你按下 enter 的话,就会出现如下画面:

    需要输入账号密码的环境

    你可能会怀疑,怪了!为啥 4, 5 需要输入密码才行?而且一定要 vbird 这个系统管理员的密码才可接受?使用 dmstai 就不可以! 这是因为我们在 4, 5 忘记加上 --users 也忘记加上 --restricted 了!因此这两个项目『一定要系统管理员』才能够进入与修改。

    最后,你在第 6 个菜单上面输入 e 来想要修改参数时,输入的帐密确实是 dmtsai 的帐密,但是,就是无法修改参数耶!怎么回事啊? 我们前面讲过了, grub2 两个基本的功能 (1)修改参数与 (2)进入菜单启动模式,只有系统管理员能够修改参数,一般用户只能选择可用的启动菜单啦! 这样说,终于理解了吧?哈哈!

    问:

    我的默认菜单里面没有加上 --unrestricted 项目,同时已经配置了 set superusers="vbird" 了, 那请教一下,启动的时候能不能顺利启动 (没有输入账密的情况下?)

    答:

    因为没有写上 --unrestricted 的项目,同时又加上了 superusers="vbird" 的配置项目,这表示『 grub.cfg 内的所有参数都已经受到限制』了, 所以,当倒数读秒结束后,系统会叫出账号密码输入的窗口给你填写,如果没有填写就会一直卡住了!因此无法顺利启动喔!

     

    展开全文
  • grub2设置

    千次阅读 2018-03-25 12:24:25
    grub2修改启动顺序 方法一: 查看所有的entry gsl@linux-13kr:/boot/grub2&gt; sudo awk -F \' '$1=="menuentry " {print i++ " : " $2}' /boot/grub2/grub.cfg 0 : openSUSE Leap ...

    grub2修改启动顺序

    方法一:

    • 查看所有的entry
    gsl@linux-13kr:/boot/grub2> sudo awk -F \' '$1=="menuentry " {print i++ " : " $2}' /boot/grub2/grub.cfg 
    0 : openSUSE Leap 42.3
    1 : Windows 10 (loader) (on /dev/nvme0n1p1)
    2 : Ubuntu 16.04.4 LTS (16.04) (on /dev/nvme0n1p2)

    和实际情况还是有出入的,可能表达式写的有问题

    • 查看当前default的entry
    [root@dpdk grub2]# grub2-editenv list
    saved_entry=CentOS Linux (3.10.0-693.11.1.el7.x86_64) 7 (Core)
    • 修改为指定的entry
    [root@dpdk grub2]# grub2-set-default 2
    [root@dpdk grub2]# grub2-editenv list
    saved_entry=2

    方法二:
    打开/etc/default/grub文件,这里有一些默认的配置:
    这个是opensuse的文件。

    # If you change this file, run 'grub2-mkconfig -o /boot/grub2/grub.cfg' afterwards to update
    # /boot/grub2/grub.cfg.
    
    # Uncomment to set your own custom distributor. If you leave it unset or empty, the default
    # policy is to determine the value from /etc/os-release
    GRUB_DISTRIBUTOR=
    GRUB_DEFAULT=saved
    GRUB_HIDDEN_TIMEOUT=0
    GRUB_HIDDEN_TIMEOUT_QUIET=true
    GRUB_TIMEOUT=8
    GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/disk/by-uuid/7355b565-e5b0-4ac2-b089-dfc23a1f5189 splash=silent quiet showopts resume=/dev/disk/by-uuid/7355b565-e5b0-4ac2-b089-dfc23a1f5189 splash=silent quiet showopts resume=/dev/nvme0n1p5 splash=silent quiet showopts"
    GRUB_CMDLINE_LINUX=""
    
    # Uncomment to automatically save last booted menu entry in GRUB2 environment
    
    # variable `saved_entry'
    # GRUB_SAVEDEFAULT="true"
    #Uncomment to enable BadRAM filtering, modify to suit your needs
    
    # This works with Linux (no patch required) and with any kernel that obtains
    # the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
    # GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
    #Uncomment to disable graphical terminal (grub-pc only)
    
    GRUB_TERMINAL="gfxterm"
    # The resolution used on graphical terminal
    #note that you can use only modes which your graphic card supports via VBE
    
    # you can see them in real GRUB with the command `vbeinfo'
    GRUB_GFXMODE="auto"
    # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
    # GRUB_DISABLE_LINUX_UUID=true
    #Uncomment to disable generation of recovery mode menu entries
    
    # GRUB_DISABLE_LINUX_RECOVERY="true"
    #Uncomment to get a beep at grub start
    
    # GRUB_INIT_TUNE="480 440 1"
    GRUB_BACKGROUND=/boot/grub2/themes/openSUSE/background.png
    GRUB_THEME=/boot/grub2/themes/openSUSE/theme.txt
    SUSE_BTRFS_SNAPSHOT_BOOTING="true"
    GRUB_DISABLE_OS_PROBER="false"
    GRUB_ENABLE_CRYPTODISK="n"
    GRUB_CMDLINE_XEN_DEFAULT="vga=gfx-1024x768x16 vga=gfx-1024x768x16 vga=gfx-1024x768x16"

    第一项GRUB_DEFAULT就是用来修改默认启动项目的。
    saved是当前系统,或者从0开始的数字。
    0,表示第一项,依次类推。

    只要将它的值修改为需要的启动项对应的值即可。

    之后运行

    update-grub  

    更新Grub即可生效:

    修改启动时的显示分辨率

    同样是修改/etc/default/grub文件,里面有一项是GRUB_GFXMODE,模式是注释掉的。

    将它打开并修改成合适的分辨率,比如1920x1080即可。

    注意两个数字中间的其实是字母的‘x’。

    之后还是需要运行update-grub来使设置生效

    修改根据UUID来确定root设备的方式

    目前Ubuntu的最新版本(比如16.04)默认会通过UUID来确定root对应的设备,比如如下的配置(部分):

    ### BEGIN /etc/grub.d/10_linux ###
    menuentry 'openSUSE Leap 42.3'  --class opensuse --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-181ce7da-36d1-40b8-a548-f35f0547637d' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_msdos
        insmod btrfs
        set root='hd0,msdos4'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint='hd0,msdos4'  181ce7da-36d1-40b8-a548-f35f0547637d
        else
          search --no-floppy --fs-uuid --set=root 181ce7da-36d1-40b8-a548-f35f0547637d
        fi
        echo    '载入 Linux 4.4.114-42-default ...'
        linux   /boot/vmlinuz-4.4.114-42-default root=UUID=181ce7da-36d1-40b8-a548-f35f0547637d  ${extra_cmdline} resume=/dev/disk/by-uuid/7355b565-e5b0-4ac2-b089-dfc23a1f5189 splash=silent quiet showopts resume=/dev/disk/by-uuid/7355b565-e5b0-4ac2-b089-dfc23a1f5189 splash=silent quiet showopts resume=/dev/nvme0n1p5 splash=silent quiet showopts
        echo    '载入初始化内存盘...'
        initrd  /boot/initrd-4.4.114-42-default
    }
    submenu 'Advanced options for openSUSE Leap 42.3' --hotkey=1 $menuentry_id_option 'gnulinux-advanced-181ce7da-36d1-40b8-a548-f35f0547637d' {
    

    这会导致一个问题,就是你想通过镜像复制转移系统的时候出现root无法mount的问题,因为UUID对应不同的硬盘/U盘都是唯一。

    为了避免这种情况,可以在/etc/default/grub文件中找到如下的配置:

    # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
    # GRUB_DISABLE_LINUX_UUID=true

    将这个配置打开,然后运行update-grub,这样修改之后,root就会是/dev/sdx这样的形式。

    当然这样的坏处是如果有多个硬盘设备,可能这里的root就是指向了错误的设备。

    不过这个是其它问题了。

    重建grub2启动项

    重新安装了 Windows,可是启动时却找不到 Ubuntu 的启动项了
    可以使用如下两种方法之一,修复 Ubuntu 的启动:

    无法进入系统,grub损坏:

    使用 LiveCD/LiveUSB 或者硬盘安装的方法,进入一个 live 环境,挂载上原来的根分区,比如挂载为 /mnt/temp,运行命令: 创建 /mnt/temp:

    sudo mkdir /mnt/temp

    查看分区情况

    sudo fdisk -l

    挂载原来的根目录:(假设/ 在/dev/sda5,具体以查到情况为准)

    sudo mount /dev/sda5 /mnt/temp

    如果是单独分的 /boot (以 sda6 为例),则挂载它,如没有则跳过此步:

    sudo mount /dev/sda6 /mnt/temp/boot

    挂载系统目录:-B 和–bind作用一样,即绑定两个目录一致

    for i in /dev /dev/pts /proc /sys; do sudo mount -B $i /mnt/temp$i; done

    chroot 进入原系统:(chroot是改变根目录)

    sudo chroot /mnt/temp

    重新安装 Grub2 到 MBR 并更新启动项:
    如果grub.cfg损坏,首先生成 /boot/grub2/grub.cfg:(如果没问题,这一项可以不做)

    grub2-mkconfig -o /boot/grub2/grub.cfg

    以下需要做

    grub-install /dev/sda
    update-grub

    其实对于主引导记录来说就,它并不是存放于/dev/sda3,也不是/dev/sda1,更加不是/dev/sda4上,而是有一个单独的小空间给他,所以这里只用写/dev/sda就可以了,而不用写/dev/sda3或者/dev/sda1了
    update-grub会搜索所有接入的磁盘中的系统,然后放入MBR中
    重新安装 GRUB 到 MBR, 并更新 GRUB,
    退出环境:

    exit

    还原系统目录:

    for i in /dev/pts /dev /proc /sys / ; do sudo umount /mnt/temp$i ; done

    可以进入windows,无法进入linux:

    如果还可已进入windows系统,可以下载easybcd这个软件,来添加其他操作系统的启动菜单,这个方法比较傻瓜,操作也简单,效果如下:
    这里写图片描述
    添加启动菜单,正确选择系统所在的分区,和原引导类型。
    这里写图片描述
    添加后的编辑查看,注意保存后才有效。
    这里写图片描述
    如果不想使用多系统启动,用这个软件删除启动项即可。

    可以进入linux,无法进入windows:

    如果可以进linux系统,进不了Windows系统,则更简单,只需进入linux系统,运行方法一中最后提到的一个命令即可。

    update-grub

    update-grub2

    可以进入linux,但不能搜索到所有的启动项

    通过上一个命令更新grub配置后,人然搜索不到其他安装过的系统,可以把找不到的系统的分区挂载起来,然后执行update-grub,即可发现启动项,或者把无法引导的系统的/boot/grub/grub.cfg中的引导该系统的条目拷贝到,当前引导系统分区中的/etc/grub.d/40_custom中。再执行update-grub.

    展开全文
  • GRUB2内核启动设置 GRUB2引导菜单加密 GRUB2引导故障及修复 救援模式管理 Rhel7破解root密码 内核升级 查看当前内核版本: uname -r 查看可升级内核: yum list kernel 升级 kernel: yum update ...
  • grub2详解

    千次阅读 2019-08-16 14:29:19
    本文主要介绍的是grub2,在文末对传统grub进行了简述,但在grub2的内容部分中包含了很多grub2和传统grub的对比。 如果仅仅是想知道grub2中的boot.img/core.img/diskboot.img/kernel.img或者传统grub中stage1/stage1_...
  • GRUB2基础——增加自定义命令

    千次阅读 2019-11-03 21:35:37
    介绍如何在GRUB2中添加自定义的命令。
  • Linux下如何修改grub.cfg

    万次阅读 2018-02-04 15:52:00
    grub2的启动配置文件grub.cfg grub2的启动配置文件grub.cfg是在/boot/grub/grub.cfg,而不是以前的memu.lst。 如果你是多系统,有Ubuntu和windows,那么用下面的命令,可以使grub2得到可以启动的系统。 sudo ...
  • grub2配置

    万次阅读 2010-08-26 20:25:00
    grub2配置grub2-mkconfig -o /boot/grub2/grub.cfg 自动生成一个grub2配置文件。grub2-setup /dev/sda 这使用默认的文件向设备上灌入grub。 如果出现如下错误: grub-probe:error: Cannot find a GRUB ...
  • grub2与grub区别

    万次阅读 2016-05-13 17:43:21
    GRUB legacy(版本为0.97)是指GRUB,而非GRUB2检测版本:$ grub-install -v grub-install (GNU GRUB 1.98-1ubuntu10)GRUB2与GRUB的区别:1.GRUB2引导菜单启动项是从/boot自动生成的,不是有menu.lst配置的。...
  • linux更改grub主题

    万次阅读 2019-09-08 13:47:33
    linux更改grub主题 在这个网站下载主题 将主题解压后,移动到/boot/grub下,找到theme.txt所在的位置 打开 /etc/default/grub 文件 打开grub后,更改GRUB_THEME GRUB_THEME=/boot/grub/poly-dark-master/...
  • Centos7 修复grub

    万次阅读 2017-12-07 16:01:42
    Centos7 修复grub如果grub配置文件丢失,开机后会直接进入grub界面,显示为grub>: 找到centos7 的boot分区1) 先使用ls命令在 grub>下输入以下命令:ls会罗列所有的磁盘分区信息,比方说:(hd0,1),(hd0,5),(hd0,3),...
  • CentOS 7 下的update-grub命令的用法

    万次阅读 2017-08-02 09:20:59
     CentOS 7 下的update-grub命令的用法 发布时间:2017-04-19 00:30:04,浏览358次 ...在Ubuntu下面经常使用update-grub来更新调整后的grub设置以...在centos7下的update-grub命令是:grub2-mkconfig -o /boot/
  • 修改grub默认启动顺序

    万次阅读 2014-10-09 17:10:39
    修改grub默认启动顺序
  • 修改Grub默认启动项

    万次阅读 2017-11-17 09:38:09
    一般情况下,有人可能直接修改GRUB配置文件“/boot/grub/grub.cfg”,但使用“sudu vim /boot/grub/grub.cfg”发现提示这个是系统自动生成的文件,不建议直接编辑,而应该到“/etc/grub.d”和“/etc/default/grub”...
  • Grub Rescue来修复Grub 问题

    万次阅读 2010-04-17 22:51:00
    grub2几种修复方法1. 双系统重装windows造成grub2被改写的修复方法一 grub4dos0.4.4在Windows启动项上加上grub4dos启动(不多说了,看置顶贴),重启选择进入grub,在命令行下输入(/boot单独分区的去掉 /boot)代码:...
  • 装了Ubuntu16.04默认的grub启动界面真是难看到死,改一改主题。 1.下载Grub主题包 点这里选择自己喜欢的主题包 我选了这个 Poly light的主题包 点击下面的Files 之后在下面点击下载按钮 2.创建...
  • Linux启动时显示Grub命令行及修改

    万次阅读 2017-05-20 09:38:45
    linux修复引导菜单,出现grub命令提示符,使用命令进入系统。
  • ubuntu开机出现grub 解决办法

    万次阅读 多人点赞 2018-08-04 23:01:39
    grub是引导程序,它可以引导多操作系统。 开机出现grub ,多半是grub文件损坏了。下面介绍修复方法 查找grub所在的分区,ubuntu没有另外建分区是在/boot/grub文件夹 # 第一步:输入ls出现(hd0,msods1),(hd0,...
  • CentOS7设置GRUB系统内核开机选单

    万次阅读 2018-01-03 17:43:48
    CentOS7设置GRUB系统内核开机选单   方法一:(创建、查看、编辑、...grub2-mkconfig -o /boot/grub2/grub.cfg #说明:/boot/grub2/grub.cfg文件不可手工编辑   #查看可选的GRUB内核配置开机选单 awk -F\' '$1=="menu
1 2 3 4 5 ... 20
收藏数 85,703
精华内容 34,281
关键字:

grub2