Jak wyświetlić „menuentries” GRUB-a w wierszu poleceń?

Odpowiedzi:

31

Za pomocą awk

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

daje pełną listę wszystkich pozycji menu w grub.cfg.

AB
źródło
1
Nie musisz włączać grep do awk, awk dopasuje wzór do / foo /
Panther
1
awk -F\' '/menuentry / {print $2}' /boot/grub/grub.cfg
Panther
AB Zgadzam się z @ bodhi.zazen . Jeśli edytujesz i zostawiasz mi notatkę, wrócę i głosuję!
Fabby,
@ Fabby notatkę dla ciebie. OMG To były moje pierwsze kroki awk. : \
AB
3
Dodaj numer wyjściowy do wyjścia: awk -F\' '/menuentry / { print i++, $2}' /boot/grub/grub.cfgdo użyciagrub-set-default
mikezter
8

Kolorowy zrzut ekranu (krótka wersja)

Koło używać myszki do przewijania, Home, End, PgUp, PgDn, oraz klucze do poruszania się po menu.

grub-menu.sh

Tekstowy zrzut ekranu (długa wersja)

Skrypt bash używa whiptailzamiast dialogwyświetlać menu. Jedną z zalet jest to, że możesz skopiować obraz terminala do schowka jako tekst i wkleić go na tej stronie jako tekst. Inne zalety to:

  • Obsługa kółka przewijania myszy
  • Szybsza wydajność
  • dialognie jest domyślnie instalowany na Ubuntu Server lub Lubuntu. whiptailjest dołączony domyślnie.

Oto zrzut ekranu tekstowego:

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>                      │ 
        │                                                                          │ 
        └──────────────────────────────────────────────────────────────────────────┘ 

Podświetl wpis i naciśnij Enter

Użyj klawiszy nawigacyjnych, aby podświetlić opcję i naciśnij, Enteraby zobaczyć załadowane sterowniki jądra grubi parametry rozruchowe przekazane grubdo jądra podczas uruchamiania:

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 skrypt bash

grub-menu.sh ma tylko jedną opcję dostosowania:

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

Ustaw wartość na true(ukryj dodatkowe wpisy) lub false(wyświetl wszystkie wpisy).

Domyślny format można zastąpić podczas wywoływania skryptu za pomocą:

grub-menu.sh short

lub:

grub-menu.sh long

Kod:

#!/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

WinEunuuchs2Unix
źródło
8

Dokładnie to mnie denerwuje od ponad roku - dlatego zrobiłem szybki i brudny skrypt, aby to zrobić. Mam nadzieję, że to pomaga innym?

To układa nazwy w kolejce push / pop, ale nie indeksuje menu, więc może być lepiej, ale posunąłem się tak daleko, jak mogłem.

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

Tutaj możesz zobaczyć zrzut ekranu z mojego pudełka pokazujący, że działa wprowadź opis zdjęcia tutaj

Jak wspomniano w komentarzu z 2019/8 r., Wspomniałem powyżej, wykonując „temp boot”. Ten pomysł był początkowo początkiem mojego skryptu, a metoda temp boot pochodzi z innego postu i wygląda mniej więcej tak

  1. Ustaw GRUB_DEFAULT na GRUB_DEFAULT = zapisano # vi /etc/default/grub
  2. Zaktualizuj konfigurację grub w / boot # sudo update-grub
  3. Ustaw domyślny system operacyjny do załadowania (ładuje się przy każdym ponownym uruchomieniu komputera) # sudo grub-set-default 0
  4. Kiedy trzeba załadować inny system operacyjny (numer to numer menu systemu operacyjnego, jak w /boot/grub/grub.cfg, spowoduje to załadowanie innego systemu operacyjnego tylko raz podczas następnego restartu - restart należy uruchomić ręcznie): # sudo grub-reboot 4

Patrz: https://ubuntuforums.org/showthread.php?t=1310463

Lucien Murray-Pitts
źródło
+1 Podoba mi się polecenie pushi popw twojej odpowiedzi. Szkoda, że ​​ich nie znałem, zanim napisałem odpowiedź.
WinEunuuchs2Unix
Czy możesz również udostępnić grub-tempboot.sh?
Autodidact
test1. Ustaw GRUB_DEFAULT na GRUB_DEFAULT = zapisany (/ etc / default / grub) 2. Zaktualizuj konfigurację grub w / boot #sudo update-grub 3. Ustaw domyślny system operacyjny na ładowanie (ładuje się przy każdym ponownym uruchomieniu komputera) # sudo grub -set-default 0 4. Gdy trzeba załadować inny system operacyjny (liczba to numer menu systemu operacyjnego, jak w /boot/grub/grub.cfg, spowoduje to załadowanie innego systemu operacyjnego tylko raz podczas następnego restartu - restart należy uruchomić ręcznie): sudo grub-reboot 4
Lucien Murray-Pitts
3

To powinien być odpowiedni „ciąg” ...

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

Ostatnia rura usuwa białe znaki na początku każdego wiersza i koryguje sekwencję numerów zgodnie z wprowadzeniem numeru grub. Przykładowe dane wyjściowe:

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

Jeśli chcesz zobaczyć wszystkie wpisy, również zaawansowane, możesz użyć

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

ale sekwencja liczb nie nadaje się do użycia z grub-set-default.

Stefano Bizzarri
źródło
6
To pokazuje tylko menu najwyższego poziomu. Zaawansowane opcje podmenu brakuje.
WinEunuuchs2Unix
1
Czy możesz wyjaśnić, co robią potokowe polecenia i jak jest to lepsze niż zaakceptowana odpowiedź ?
Melebius
Dla mnie działało to lepiej, ponieważ drukuje również numery wejścia
Zac
2

Właśnie dowiedziałem się, że możesz po prostu użyć autouzupełniania ( tabdwukrotne naciśnięcie ) poleceń takich jak grub-rebootlub grub-set-default, a wyświetli się lista dostępnych pozycji menu rozruchu. Następnie możesz po prostu skopiować tytuł, który chcesz dosłownie, nie musisz używać numeru.

Niestety z jakiegoś powodu moja instalacja systemu Windows 7 nie wyświetla się w ten sposób.

DanMan
źródło
1

Inny awk one-liner, który obsługuje podmenu:

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

Może to być omylne, ponieważ \ t służy do identyfikowania pozycji podmenu.

Max
źródło
0

W OpenSuSE grub2-once zapewnia identyfikator menu, którego można następnie użyć w innych poleceniach. Jednak niewiele pomocy dla użytkowników Ubuntu.

# 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)
Paranoidalny
źródło
Prawdopodobnie powinieneś udostępnić lokalizację, z której dostałeś grub2-raz
Charles Green
Chociaż chodzi o ubuntu, używam OpenSuSE i instaluje wszystkie polecenia grub v2 jako grub2 - ????. Kiedy szukałem sposobu na uzyskanie listy menu grub, jest to pytanie, które można znaleźć niezależnie od smaku linuksa, więc pomyślałem, że moja odpowiedź może być pomocna dla innych. Nie zdawałem sobie sprawy, że polecenie grub2-once wydaje się być unikalne dla suse (brak równoważnego grub-raz w Ubuntu). Zmienię swoją odpowiedź, aby to odzwierciedlić
Paranoid
Wygląda na przydatne narzędzie ...
Charles Green