显示grub菜单和选项而无需重启?

我想从命令行显示grub菜单。 另外,要选择grub引导菜单选项并按Enter键以查看加载内核前驱动程序的内容以及加载内核时引导的引导参数。

从命令行执行此操作的原因:

  • 重新启动以查看grub菜单需要时间。
  • 拍摄grub菜单并在网站上发布图片很尴尬。 当Ubuntu启动并运行时,更容易抓取屏幕截图。
  • 使用e edit grub菜单选项并拍照通常很困难,因为屏幕难以阅读。 使用此function,您可以复制和粘贴。
  • 使用此函数可能更容易显示所有内核版本而不是apt list --installed | grep linux-image apt list --installed | grep linux-imagels /boot/vml*
  • 要快速查看grub菜单编号对grub-rebootgrub-set-default命令很有用。

如何从命令行绘制grub菜单,查看内部grub菜单条目编号并显示给定选项的引导参数?

更新于2018年5月7日

开发脚本: Bash脚本将Ubuntu克隆到新分区以进行测试18.04 LTS升级我发现你得到一些荒谬的长菜单选项导致菜单恶意:

 4>8 Ubuntu, with Linux 4.14.30-041430-generic (recovery mode) (on /dev/nvme0n1p8) 

今天通过截断超过68个字符的行修复了这个问题。

2018年4月5日更新

此更新介绍了grub-menu.sh比以前的答案更优越的版本(仍在下面提供)。 新的grub菜单包括:

  • 显示grub 2菜单条目编号。 即0 1>0 1>12
  • 可以设置没有(upstart)(recover mode)子菜单选项的默认短版本。
  • 参数1可以作为shortlong传递以覆盖默认值。
  • 列标题基于shortlong设置动态格式化。

彩色屏幕截图(短版)

grub-menu.sh

文字截图(长版)

 Grub Version: 2.02~beta2-36ubuntu3.15 ┌─────────┤ Use arrow, page, home & end keys. Tab toggle option ├──────────┐ │ Menu No. --------------- Menu Name --------------- │ │ │ │ 0 Ubuntu ↑ │ │ 1 Advanced options for Ubuntu ▮ │ │ 1>0 Ubuntu, with Linux 4.14.31-041431-generic ▒ │ │ 1>1 Ubuntu, with Linux 4.14.31-041431-generic (upstart) ▒ │ │ 1>2 Ubuntu, with Linux 4.14.31-041431-generic (recovery mode) ▒ │ │ 1>3 Ubuntu, with Linux 4.14.30-041430-generic ▒ │ │ 1>4 Ubuntu, with Linux 4.14.30-041430-generic (upstart) ▒ │ │ 1>5 Ubuntu, with Linux 4.14.30-041430-generic (recovery mode) ▒ │ │ 1>6 Ubuntu, with Linux 4.14.27-041427-generic ▒ │ │ 1>7 Ubuntu, with Linux 4.14.27-041427-generic (upstart) ▒ │ │ 1>8 Ubuntu, with Linux 4.14.27-041427-generic (recovery mode) ▒ │ │ 1>9 Ubuntu, with Linux 4.14.24-041424-generic ▒ │ │ 1>10 Ubuntu, with Linux 4.14.24-041424-generic (upstart) ▒ │ │ 1>11 Ubuntu, with Linux 4.14.24-041424-generic (recovery mode) ▒ │ │ 1>12 Ubuntu, with Linux 4.14.23-041423-generic ▒ │ │ 1>13 Ubuntu, with Linux 4.14.23-041423-generic (upstart) ↓ │ │ │ │ │ │   │ │ │ └──────────────────────────────────────────────────────────────────────────┘ 

grub-menu.sh bash脚本

以前的版本grub-display.shgrub-display-lite.sh在代码中需要许多调整选项。 grub-menu.sh只有一个调整选项:

 # Default for hide duplicate and triplicate options with (upstart) and (recovery mode)? HideUpstartRecovery=false 

将值设置为truefalse

使用以下方法调用脚本时,可以覆盖默认格式:

 grub-menu.sh short 

要么:

 grub-menu.sh long 

代码:

 #!/bin/bash # NAME: grub-menu.sh # PATH: $HOME/bin # DESC: Written for AU Q&A: https://askubuntu.com/q/1019213/307523 # DATE: Apr 5, 2018. Modified: May 7, 2018. # $TERM variable may be missing when called via desktop shortcut CurrentTERM=$(env | grep TERM) if [[ $CurrentTERM == "" ]] ; then notify-send --urgency=critical "$0 cannot be run from GUI without TERM environment variable." exit 1 fi AllMenusArr=() # All menu options. # Default for hide duplicate and triplicate options with (upstart) and (recovery mode)? HideUpstartRecovery=false if [[ $1 == short ]] ; then HideUpstartRecovery=true # override default with first passed parameter "short" elif [[ $1 == long ]] ; then HideUpstartRecovery=false # override default with first passed parameter "long" fi SkippedMenuEntry=false # Don't change this value, automatically maintained InSubMenu=false # Within a line beginning with `submenu`? InMenuEntry=false # Within a line beginning with `menuentry` and ending in `{`? NextMenuEntryNo=0 # Next grub internal menu entry number to assign # Major / Minor internal grub submenu numbers, ie `1>0`, `1>1`, `1>2`, etc. ThisSubMenuMajorNo=0 NextSubMenuMinorNo=0 CurrTag="" # Current grub internal menu number, zero based CurrText="" # Current grub menu option text, ie "Ubuntu", "Windows...", etc. SubMenuList="" # Only supports 10 submenus! Numbered 0 to 9. Future use. while read -r line; do # Example: " }" BlackLine="${line//[[:blank:]]/}" # Remove all whitespace if [[ $BlackLine == "}" ]] ; then # Add menu option in buffer if [[ $SkippedMenuEntry == true ]] ; then NextSubMenuMinorNo=$(( $NextSubMenuMinorNo + 1 )) SkippedMenuEntry=false continue fi if [[ $InMenuEntry == true ]] ; then InMenuEntry=false if [[ $InSubMenu == true ]] ; then NextSubMenuMinorNo=$(( $NextSubMenuMinorNo + 1 )) else NextMenuEntryNo=$(( $NextMenuEntryNo + 1 )) fi elif [[ $InSubMenu == true ]] ; then InSubMenu=false NextMenuEntryNo=$(( $NextMenuEntryNo + 1 )) else continue # Future error message? fi # Set maximum CurrText size to 68 characters. CurrText="${CurrText:0:67}" AllMenusArr+=($CurrTag "$CurrText") fi # Example: "menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu" ... # "submenu 'Advanced options for Ubuntu' $menuentry_id_option" ... if [[ $line == submenu* ]] ; then # line starts with `submenu` InSubMenu=true ThisSubMenuMajorNo=$NextMenuEntryNo NextSubMenuMinorNo=0 SubMenuList=$SubMenuList$ThisSubMenuMajorNo CurrTag=$NextMenuEntryNo CurrText="${line#*\'}" CurrText="${CurrText%%\'*}" AllMenusArr+=($CurrTag "$CurrText") # ie "1 Advanced options for Ubuntu" elif [[ $line == menuentry* ]] && [[ $line == *"{"* ]] ; then # line starts with `menuentry` and ends with `{` if [[ $HideUpstartRecovery == true ]] ; then if [[ $line == *"(upstart)"* ]] || [[ $line == *"(recovery mode)"* ]] ; then SkippedMenuEntry=true continue fi fi InMenuEntry=true if [[ $InSubMenu == true ]] ; then : # In a submenu, increment minor instead of major which is "sticky" now. CurrTag=$ThisSubMenuMajorNo">"$NextSubMenuMinorNo else CurrTag=$NextMenuEntryNo fi CurrText="${line#*\'}" CurrText="${CurrText%%\'*}" else continue # Other stuff - Ignore it. fi done < /boot/grub/grub.cfg LongVersion=$(grub-install --version) ShortVersion=$(echo "${LongVersion:20}") DefaultItem=0 if [[ $HideUpstartRecovery == true ]] ; then MenuText="Menu No. ----------- Menu Name -----------" else MenuText="Menu No. --------------- Menu Name ---------------" fi while true ; do Choice=$(whiptail \ --title "Use arrow, page, home & end keys. Tab toggle option" \ --backtitle "Grub Version: $ShortVersion" \ --ok-button "Display Grub Boot" \ --cancel-button "Exit" \ --default-item "$DefaultItem" \ --menu "$MenuText" 24 76 16 \ "${AllMenusArr[@]}" \ 2>&1 >/dev/tty) clear if [[ $Choice == "" ]]; then break ; fi DefaultItem=$Choice for (( i=0; i < ${#AllMenusArr[@]}; i=i+2 )) ; do if [[ "${AllMenusArr[i]}" == $Choice ]] ; then i=$i+1 MenuEntry="menuentry '"${AllMenusArr[i]}"'" break fi done TheGameIsAfoot=false while read -r line ; do if [[ $line = *"$MenuEntry"* ]]; then TheGameIsAfoot=true ; fi if [[ $TheGameIsAfoot == true ]]; then echo $line if [[ $line = *"}"* ]]; then break ; fi fi done < /boot/grub/grub.cfg read -p "Press  to continue" done exit 0 

以前的版本(不推荐)

以下是菜单条目编号遵循grub 1格式的原始答案。

grub-display.sh显示grub菜单选项和参数

如果不依赖第三方应用程序,您可以使用bash脚本显示任何给定选项的grub菜单和引导参数。 引导参数不仅仅是cat /proc/cmdline值。 它们还包括在Linux启动之前加载的驱动程序。

grub-display.sh bash脚本

以下是您可以复制和粘贴的完整程序列表:

 #!/bin/bash # NAME: grub-display.sh # PATH: $HOME/bin # DESC: Written for AU Q&A: https://askubuntu.com/q/1019213/307523 # DATE: Mar 24, 2018. Modified: Mar 26, 2018. # $TERM variable may be missing when called via desktop shortcut CurrentTERM=$(env | grep TERM) if [[ $CurrentTERM == "" ]] ; then notify-send --urgency=critical "$0 cannot be run from GUI without TERM environment variable." exit 1 fi # Must have the dialog package. On Servers, not installed by default command -v dialog >/dev/null 2>&1 || { echo >&2 "dialog package required but it is not installed. Aborting."; exit 99; } # Version without upstart and recovery options displayed #awk -F\' '/menuentry / { print i++, $2}' /boot/grub/grub.cfg \ # | grep -v upstart | grep -v recovery > ~/.grub-display-menu # Version with upstart and recovery options displayed awk -F\' '/menuentry / { print i++, $2}' /boot/grub/grub.cfg \ > ~/.grub-display-menu MenuArr=() while read -r line; do MenuNmbr=${line%% *} MenuName=${line#* } MenuArr+=($MenuNmbr "$MenuName") done < ~/.grub-display-menu rm ~/.grub-display-menu LongVersion=$(grub-install --version) ShortVersion=$(echo "${LongVersion:20}") DefaultItem=0 while true ; do Choice=$(dialog \ --title "Use arrow, page, home & end keys. Tab toggle option" \ --backtitle "Grub Version: $ShortVersion" \ --ok-label "Display Grub Boot" \ --cancel-label "Exit" \ --default-item "$DefaultItem" \ --menu "Menu Number ----------- Menu Name ----------" 24 76 16 \ "${MenuArr[@]}" \ >/dev/tty) clear if [[ $Choice == "" ]]; then break ; fi DefaultItem=$Choice for (( i=0; i < ${#MenuArr[@]}; i=i+2 )) ; do if [[ "${MenuArr[i]}" == $Choice ]] ; then i=$i+1 MenuEntry="menuentry '"${MenuArr[i]}"'" break fi done TheGameIsAfoot=false while read -r line ; do if [[ $line = *"$MenuEntry"* ]]; then TheGameIsAfoot=true ; fi if [[ $TheGameIsAfoot == true ]]; then echo $line if [[ $line = *"}"* ]]; then break ; fi fi done < /boot/grub/grub.cfg read -p "Press  to continue" done exit 0 

Ubuntu Server用户请注意

这个bash脚本是为Ubuntu Desktop设计的。 对于默认情况下没有安装dialog包的Ubuntu Server和其他Linux发行版,下面包含一个名为grub-display-lite.sh的不同脚本。 该版本使用whiptail而不是dialog

将菜单大小减少66%

要缩短显示的grub菜单选项列表,可以删除(upstart)(recovery)选项。 要做到这一点,请取消注释这些行:

 # Version without upstart and recovery options displayed awk -F\' '/menuentry / { print i++, $2}' /boot/grub/grub.cfg \ | grep -v upstart | grep -v recovery > ~/.grub-display-menu 

然后对这些行应用注释:

 # Version with upstart and recovery options displayed #awk -F\' '/menuentry / { print i++, $2}' /boot/grub/grub.cfg \ # > ~/.grub-display-menu 

截图

这是从命令行调用时的样子。 不幸的是我无法复制和粘贴菜单,不得不使用Print Screen

平头display.sh.png

关闭鼠标支持以进行复制和粘贴

  Grub Version: 2.02~beta2-36ubuntu3.15 ────────────────────────────────────────────────────────────────────────────────────────── ┌──────────Use arrow, page, home & end keys. Tab toggle option─────────────┐ │ Menu Number ----------- Menu Name ---------- │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ 0 Ubuntu │ │ │ │ 1 Ubuntu, with Linux 4.14.30-041430-generic │ │ │ │ 2 Ubuntu, with Linux 4.14.30-041430-generic (upstart) │ │ │ │ 3 Ubuntu, with Linux 4.14.30-041430-generic (recovery mode) │ │ │ │ 4 Ubuntu, with Linux 4.14.27-041427-generic │ │ │ │ 5 Ubuntu, with Linux 4.14.27-041427-generic (upstart) │ │ │ │ 6 Ubuntu, with Linux 4.14.27-041427-generic (recovery mode) │ │ │ │ 7 Ubuntu, with Linux 4.14.24-041424-generic │ │ │ │ 8 Ubuntu, with Linux 4.14.24-041424-generic (upstart) │ │ │ │ 9 Ubuntu, with Linux 4.14.24-041424-generic (recovery mode) │ │ │ │ 10 Ubuntu, with Linux 4.14.23-041423-generic │ │ │ │ 11 Ubuntu, with Linux 4.14.23-041423-generic (upstart) │ │ │ │ 12 Ubuntu, with Linux 4.14.23-041423-generic (recovery mode) │ │ │ │ 13 Ubuntu, with Linux 4.14.21-041421-generic │ │ │ │ 14 Ubuntu, with Linux 4.14.21-041421-generic (upstart) │ │ │ │ 15 Ubuntu, with Linux 4.14.21-041421-generic (recovery mode) │ │ │ └────↓(+)──────────────────────────────────────────────────────16%─────┘ │ │ │ ├──────────────────────────────────────────────────────────────────────────┤ │  < Exit > │ └──────────────────────────────────────────────────────────────────────────┘ 

启用默认鼠标支持后,您无法将屏幕复制到剪贴板,但必须使用“ 打印屏幕”来显示图形屏幕快照。 为了支持复制和粘贴,您需要通过搜索以下行来禁用鼠标支持:

  --default-item "$DefaultItem" \ --no-mouse \ --menu "Menu Number ----------- Menu Name ----------" 24 76 16 \ 

参数--no-mouse已插入--default-item下面。 这意味着您可以通过突出显示文本并按Ctrl + C来放松鼠标支持但获得更好的分辨率并复制到剪贴板function。

显示grub引导参数

使用导航键突出显示一个选项,然后按Enter键查看其引导参数:

 menuentry 'Ubuntu, with Linux 4.14.27-041427-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.14.27-041427-generic-advanced-f3f8e7bc-b337-4194-88b8-3a513f6be55b' { recordfail savedefault load_video gfxmode $linux_gfx_mode insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root f3f8e7bc-b337-4194-88b8-3a513f6be55b else search --no-floppy --fs-uuid --set=root f3f8e7bc-b337-4194-88b8-3a513f6be55b fi echo 'Loading Linux 4.14.27-041427-generic ...' linux /boot/vmlinuz-4.14.27-041427-generic root=UUID=f3f8e7bc-b337-4194-88b8-3a513f6be55b ro quiet splash loglevel=0 vga=current udev.log-priority=3 fastboot kaslr acpiphp.disable=1 crashkernel=384M-2G:128M,2G-:256M $vt_handoff echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-4.14.27-041427-generic } Press  to continue 

Grub菜单条目#94

 menuentry 'Windows Boot Manager (on /dev/nvme0n1p2)' --class windows --class os $menuentry_id_option 'osprober-efi-D656-F2A8' { savedefault insmod part_gpt insmod fat if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root D656-F2A8 else search --no-floppy --fs-uuid --set=root D656-F2A8 fi chainloader /EFI/Microsoft/Boot/bootmgfw.efi } Press  to continue 

Grub菜单条目#96

 menuentry 'System setup' $menuentry_id_option 'uefi-firmware' { fwsetup } Press  to continue 

grub-display-lite.sh于Ubuntu Server的grub-display-lite.sh

Ubuntu Server和Lubuntu没有像Ubuntu Desktop那样默认安装dialog包。 已经为这些用户编写了一个基于whiptail软件包的不同版本,该软件包默认包含在大多数Linux发行版中。

whiptail的缺点是function较少,但在这种情况下不使用它们。 另一个缺点似乎是颜色较少,但这可以使一些人更容易阅读。 在dialog有一些优点,例如复制到剪贴板,鼠标滚轮支持以及可能更快的处理。

grub-display-lite.sh bash脚本

 #!/bin/bash # NAME: grub-display-lite.sh # PATH: $HOME/bin # DESC: Written for AU Q&A: https://askubuntu.com/q/1019213/307523 # DATE: Mar 26, 2018. # NOTE: "lite" version written for Ubuntu Server and Lubuntu which do # not have `dialog` installed by default. `whiptail` is used # instead. Nice consequences are better resolution, mouse scroll # wheel and copy to clipboard support. # $TERM variable may be missing when called via desktop shortcut CurrentTERM=$(env | grep TERM) if [[ $CurrentTERM == "" ]] ; then notify-send --urgency=critical "$0 cannot be run from GUI without TERM environment variable." exit 1 fi # Version without upstart and recovery options displayed awk -F\' '/menuentry / { print i++, $2}' /boot/grub/grub.cfg \ | grep -v upstart | grep -v recovery > ~/.grub-display-menu # Version with upstart and recovery options displayed #awk -F\' '/menuentry / { print i++, $2}' /boot/grub/grub.cfg \ # > ~/.grub-display-menu MenuArr=() while read -r line; do MenuNmbr=${line%% *} MenuName=${line#* } MenuArr+=($MenuNmbr "$MenuName") done < ~/.grub-display-menu rm ~/.grub-display-menu LongVersion=$(grub-install --version) ShortVersion=$(echo "${LongVersion:20}") DefaultItem=0 while true ; do Choice=$(whiptail \ --title "Use arrow, page, home & end keys. Tab toggle option" \ --backtitle "Grub Version: $ShortVersion" \ --ok-button "Display Grub Boot" \ --cancel-button "Exit" \ --default-item "$DefaultItem" \ --menu "Menu Number ----------- Menu Name ----------" 24 76 16 \ "${MenuArr[@]}" \ >/dev/tty) clear if [[ $Choice == "" ]]; then break ; fi DefaultItem=$Choice for (( i=0; i < ${#MenuArr[@]}; i=i+2 )) ; do if [[ "${MenuArr[i]}" == $Choice ]] ; then i=$i+1 MenuEntry="menuentry '"${MenuArr[i]}"'" break fi done TheGameIsAfoot=false while read -r line ; do if [[ $line = *"$MenuEntry"* ]]; then TheGameIsAfoot=true ; fi if [[ $TheGameIsAfoot == true ]]; then echo $line if [[ $line = *"}"* ]]; then break ; fi fi done < /boot/grub/grub.cfg read -p "Press  to continue" done exit 0 

grub-display-lite.sh bash脚本与grub-display.sh基本相同,但如果没有安装dialog则没有错误消息。 还有一些whiptail参数有不同的名称。

grub-display-lite.sh截图

彩屏似乎比使用dialog包的grub-display更容易阅读:

grub-display-lite.sh

这是基于文本的图像,无需修改即可复制到剪贴板:

 Grub Version: 2.02~beta2-36ubuntu3.15 ┌─────────┤ Use arrow, page, home & end keys. Tab toggle option ├──────────┐ │ Menu Number ----------- Menu Name ---------- │ │ │ │ 55 Ubuntu, with Linux 4.13.9-041309-generic ↑ │ │ 58 Ubuntu, with Linux 4.10.0-42-generic ▒ │ │ 61 Ubuntu, with Linux 4.10.0-40-generic ▒ │ │ 64 Ubuntu, with Linux 4.10.0-38-generic ▒ │ │ 67 Ubuntu, with Linux 4.10.0-37-generic ▒ │ │ 70 Ubuntu, with Linux 4.10.0-28-generic ▒ │ │ 73 Ubuntu, with Linux 4.9.77-040977-generic ▒ │ │ 76 Ubuntu, with Linux 4.9.76-040976-generic ▒ │ │ 79 Ubuntu, with Linux 4.4.0-104-generic ▒ │ │ 82 Ubuntu, with Linux 4.4.0-103-generic ▒ │ │ 85 Ubuntu, with Linux 4.4.0-101-generic ▒ │ │ 88 Ubuntu, with Linux 4.4.0-98-generic ▒ │ │ 91 Ubuntu, with Linux 3.16.53-031653-generic ▒ │ │ 94 Windows Boot Manager (on /dev/nvme0n1p2) ▮ │ │ 95 Windows Boot Manager (on /dev/sda1) ▒ │ │ 96 System setup ↓ │ │ │ │ │ │   │ │ │ └──────────────────────────────────────────────────────────────────────────┘ 

如上所述,当删除(upstart)(recovery)菜单选项时,您可以将此处显示的grub菜单的大小减少66%。 这种情况就是这样,但结果细节线越来越窄,标题也没有完美排列。 您可以通过更改此行来调整列标题:

  --menu "Menu Number ----------- Menu Name ----------" 24 76 16 \ 

这样的事情:

  --menu " Menu Number ----------- Menu Name ----------" 24 76 16 \