Làm cách nào để liệt kê các menu của GRUB trong các dòng lệnh của GRUB?


Câu trả lời:


31

Sử dụng awk

awk -F\' '/menuentry / {print $2}' /boot/grub/grub.cfg 

cung cấp cho bạn một danh sách đầy đủ của tất cả các mục trong menu grub.cfg.


1
Bạn không cần phải chuyển grep sang awk, awk sẽ khớp mẫu với / foo /
Panther

1
awk -F\' '/menuentry / {print $2}' /boot/grub/grub.cfg
Panther

AB Tôi đồng ý với @ bodhi.zazen . Nếu bạn chỉnh sửa và để lại cho tôi một ghi chú, tôi sẽ quay lại và nâng cấp!
Fabby

@Fabby một lưu ý cho bạn. OMG Đó là những bước đầu tiên của tôi với awk. : \
AB

3
Thêm số mục nhập vào đầu ra: awk -F\' '/menuentry / { print i++, $2}' /boot/grub/grub.cfgđể sử dụng chogrub-set-default
mikezter

8

Ảnh chụp màn hình màu (phiên bản ngắn)

Sử dụng chuột cuộn bánh xe, Home, End, PgUp, PgDn, các phím điều hướng menu.

grub-menu.sh

Ảnh chụp màn hình văn bản (phiên bản dài)

Kịch bản bash sử dụng whiptailthay vì dialogđể hiển thị menu. Một lợi thế là bạn có thể sao chép hình ảnh thiết bị đầu cuối vào bảng tạm dưới dạng văn bản và dán nó vào trang web này dưới dạng văn bản. Các ưu điểm khác bao gồm:

  • Hỗ trợ chuột cuộn
  • Hiệu suất nhanh hơn
  • dialogkhông được cài đặt theo mặc định trong Ubuntu Server hoặc Lubfox. whiptailđược bao gồm theo mặc định.

Đây là một ảnh chụp màn hình văn bản:

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)        ↓    │ 
        │                                                                          │ 
        │                                                                          │ 
        │                   <Display Grub Boot>        <Exit>                      │ 
        │                                                                          │ 
        └──────────────────────────────────────────────────────────────────────────┘ 

Đánh dấu mục nhập và nhấn Enter

Sử dụng các phím điều hướng để tô sáng một tùy chọn và nhấn Enterđể xem trình điều khiển tiền nhân được tải bởi grubvà các tham số khởi động được truyền qua grubkernel khi khởi động nó:

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 <Enter> to continue

grub-menu.sh kịch bản bash

grub-menu.sh chỉ có một tùy chọn để điều chỉnh:

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

Đặt giá trị thành true(ẩn các mục nhập thêm) hoặc false(liệt kê tất cả các mục).

Định dạng mặc định có thể được ghi đè khi gọi tập lệnh bằng cách sử dụng:

grub-menu.sh short

hoặc là:

grub-menu.sh long

Mật mã:

#!/bin/bash

# NAME: grub-menu.sh
# PATH: $HOME/bin
# DESC: Written for AU Q&A: /ubuntu//q/1019213/307523
# DATE: Apr 5, 2018. Modified: July 27, 2019
# UPDT: Scroll bar was outside of dialog box. Move windo border line.

# $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

# Send output to secondary terminal such that previous history isn't cleared on exit
tput smcup

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 --clear \
        --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 80 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 <Enter> to continue"

done

# Restore output to primary terminal
tput rmcup

exit 0


8

Chính xác thì điều này đã gây khó chịu cho tôi trong hơn một năm - vì vậy tôi đã thực hiện một kịch bản nhanh và bẩn để làm điều đó. Hy vọng điều này sẽ giúp người khác?

Điều này sắp xếp các tên trong hàng đợi đẩy / pop, nhưng không lập chỉ mục menu để có thể tốt hơn nhưng tôi đã đi xa hết mức có thể.

gawk  'BEGIN {                                                                                                                       
  l=0                                                                                                                                
  menuindex= 0                                                                                                                       
  stack[t=0] = 0                                                                                                                     
}                                                                                                                                    

function push(x) { stack[t++] = x }                                                                                                  

function pop() { if (t > 0) { return stack[--t] } else { return "" }  }                                                              

{                                                                                                                                    

if( $0 ~ /.*menu.*{.*/ )                                                                                                             
{                                                                                                                                    
  push( $0 )                                                                                                                         
  l++;                                                                                                                               

} else if( $0 ~ /.*{.*/ )                                                                                                            
{                                                                                                                                    
  push( $0 )                                                                                                                         

} else if( $0 ~ /.*}.*/ )                                                                                                            
{                                                                                                                                    
  X = pop()                                                                                                                          
  if( X ~ /.*menu.*{.*/ )                                                                                                            
  {                                                                                                                                  
     l--;                                                                                                                            
     match( X, /^[^'\'']*'\''([^'\'']*)'\''.*$/, arr )                                                                               

     if( l == 0 )                                                                                                                    
     {                                                                                                                               
       print menuindex ": " arr[1]                                                                                                   
       menuindex++                                                                                                                   
       submenu=0                                                                                                                     
     } else                                                                                                                          
     {                                                                                                                               
       print "  " (menuindex-1) ">" submenu " " arr[1]                                                                               
       submenu++                                                                                                                     
     }                                                                                                                               
  }                                                                                                                                  
}                                                                                                                                    

}' /boot/grub/grub.cfg

Ở đây bạn có thể thấy một màn hình lấy từ hộp của tôi cho thấy nó đang chạy nhập mô tả hình ảnh ở đây

Như đã được yêu cầu trong một bình luận từ năm 2019/8, tôi đã đề cập ở trên khi thực hiện "khởi động tạm thời". Ý tưởng này ban đầu là kịch bản của tôi và phương thức khởi động tạm thời đến từ một bài đăng khác và nó diễn ra như thế này

  1. Đặt GRUB_DEFAULT thành GRUB_DEFAULT = đã lưu # vi /etc/default/grub
  2. Cập nhật cấu hình grub trong / boot # sudo update-grub
  3. Đặt hệ điều hành mặc định để tải (điều này sẽ tải mỗi khi bạn khởi động lại máy) # sudo grub-set-default 0
  4. Khi cần tải HĐH khác (số là số menu của HĐH như trong /boot/grub/grub.cfg, điều này sẽ chỉ tải hệ điều hành khác một lần trong lần khởi động lại tiếp theo - khởi động lại để được khởi động thủ công): # sudo grub-reboot 4

Tham chiếu: https://ubuntuforums.org/showthread.php?t=1310463


+1 Tôi thích các lệnh pushpoptrong câu trả lời của bạn. Ước gì tôi đã biết họ trước khi tôi viết câu trả lời của mình.
WinEunuuchs2Unix

Bạn cũng có thể chia sẻ grub-tempboot.sh?
Tự động hóa

test1. Đặt GRUB_DEFAULT thành GRUB_DEFAULT = đã lưu (/ etc / default / grub) 2. Cập nhật cấu hình grub trong / boot #sudo update-grub 3. Đặt hệ điều hành mặc định để tải (điều này sẽ tải mỗi khi bạn khởi động lại máy) # sudo grub -set-default 0 4. Khi cần tải HĐH khác (số là số menu của HĐH như trong /boot/grub/grub.cfg, điều này sẽ chỉ tải hệ điều hành khác một lần trong lần khởi động lại tiếp theo - khởi động lại để được khởi động thủ công): sudo grub-restart 4
Lucien Murray-Pitts

3

Đây phải là "chuỗi" đúng ...

awk -F\' '/^menuentry / {print $2}' /boot/grub/grub.cfg|cat -n|awk '{print $1-1,$1="",$0}'

Ống cuối cùng xóa khoảng trắng ở đầu mỗi hàng và sửa chuỗi số theo mục nhập số grub. Đầu ra mẫu:

0   Ubuntu
1   Memory test (memtest86+)
2   Memory test (memtest86+, serial console 115200)
3   Windows 10 (su /dev/sdc1)

Nếu bạn muốn xem tất cả các mục, cũng là nâng cao, bạn có thể sử dụng

awk -F\' '/(^|| )nuentry / {print $2}' /boot/grub/grub.cfg|cat -n|awk '{print $1-1,$1="",$0}'

nhưng dãy số không phù hợp để sử dụng với grub-set-default.


6
Điều này chỉ hiển thị menu cấp cao nhất. Các Advanced Options sub-menu là mất tích.
WinEunuuchs2Unix

1
Bạn có thể giải thích những gì các lệnh đường ống làm và làm thế nào nó tốt hơn câu trả lời được chấp nhận ?
Melebius

Đối với tôi, điều này hoạt động tốt hơn khi nó cũng in số mục nhập
Zac

2

Tôi vừa phát hiện ra rằng bạn chỉ có thể sử dụng tự động hoàn thành (nhấn tabhai lần) vào các lệnh như grub-reboothoặc grub-set-defaultnó sẽ cung cấp cho bạn một danh sách các mục nhập menu khởi động có sẵn. Sau đó, bạn có thể sao chép tiêu đề bạn muốn theo nghĩa đen, bạn không cần sử dụng số.

Thật không may, vì một số lý do, cài đặt Windows 7 của tôi không hiển thị theo cách đó.


1

Một lớp lót khác awk xử lý các menu con:

 awk -F\' '$1=="menuentry " || $1=="submenu " {print i++ " : " $2}; /\tmenuentry / {print "\t" i-1">"j++ " : " $2};' /boot/grub/grub.cfg

Điều này có thể được suy nghĩ rõ ràng, bởi vì \ t được sử dụng để xác định các mục menu con.


0

Trong OpenSuSE grub2-once cung cấp id menu mà sau đó bạn có thể sử dụng trong các lệnh khác. Không có nhiều trợ giúp cho người dùng Ubuntu mặc dù.

# grub2-once --list
     0 openSUSE Leap 42.3
     1 Advanced options for openSUSE Leap 42.3>openSUSE Leap 42.3, with Linux 4.4.172-86-default
     2 Advanced options for openSUSE Leap 42.3>openSUSE Leap 42.3, with Linux 4.4.172-86-default (recovery mode)
     3 Advanced options for openSUSE Leap 42.3>openSUSE Leap 42.3, with Linux 4.4.165-81-default
     4 Advanced options for openSUSE Leap 42.3>openSUSE Leap 42.3, with Linux 4.4.165-81-default (recovery mode)
     5 Advanced options for openSUSE Leap 42.3>openSUSE Leap 42.3, with Linux 4.4.159-73-default
     6 Advanced options for openSUSE Leap 42.3>openSUSE Leap 42.3, with Linux 4.4.159-73-default (recovery mode)
     7 openSUSE 42.1 (x86_64) (on /dev/sda8)
     8 Advanced options for openSUSE 42.1 (x86_64) (on /dev/sda8)>openSUSE Leap 42.1 (on /dev/sda8)
     9 Advanced options for openSUSE 42.1 (x86_64) (on /dev/sda8)>openSUSE Leap 42.1, with Linux 4.1.39-56-default (on /dev/sda8)
    10 Advanced options for openSUSE 42.1 (x86_64) (on /dev/sda8)>openSUSE Leap 42.1, with Linux 4.1.39-53-default (on /dev/sda8)
    11 Advanced options for openSUSE 42.1 (x86_64) (on /dev/sda8)>Install 42.3 (on /dev/sda8)

Bạn có thể nên chia sẻ vị trí mà bạn đã nhận được grub2 một lần từ
Charles Green

Mặc dù đây là về Ubuntu, tôi sử dụng OpenSuSE và nó cài đặt tất cả các lệnh grub v2 là grub2 - ????. Khi tôi đang tìm kiếm làm thế nào để có được danh sách menu grub, đây là câu hỏi được tìm thấy bất kể hương vị linux vì vậy tôi cho rằng phản ứng của tôi có thể hữu ích cho người khác. Điều mà tôi đã không nhận ra là lệnh grub2-once dường như là duy nhất đối với suse (không có grub tương đương một lần trong ubfox). Tôi sẽ sửa đổi câu trả lời của mình để phản ánh điều này
Paranoid

Có vẻ như một tiện ích tiện dụng ...
Charles Green
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.