41 votes

Comment lister les "menuentries" de Grub en ligne de commande ?

Existe-t-il un moyen de récupérer la liste des titres des "entrées de menu" de Grub ?

J'ai besoin d'un résultat dans un format qui grub-set-default acceptera, par exemple

"Ubuntu"
"Memory test (memtest86+)"
etc.

56voto

A.B. Points 84870

Utilisation de awk

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

vous donne une liste complète de toutes les entrées du menu dans grub.cfg .

16voto

WinEunuuchs2Unix Points 91128

Capture d'écran couleur (version courte)

Utilisez la molette de défilement de la souris, Home , End , PgUp , PgDn , y pour naviguer dans le menu.

grub-menu.sh

Texte Capture d'écran (version longue)

Le script de bash utilise whiptail au lieu de dialog pour afficher le menu. Un avantage est que vous pouvez copier l'image du terminal dans le presse-papiers comme texte et le coller dans ce site web en tant que texte. Les autres avantages sont les suivants :

  • Support de la molette de défilement de la souris
  • Des performances plus rapides
  • dialog n'est pas installé par défaut dans Ubuntu Server ou Lubuntu. whiptail est inclus par défaut.

Voici une capture d'écran de texte :

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>                       

Mettez l'entrée en surbrillance et appuyez sur la touche Entrée

Utilisez les touches de navigation pour mettre en surbrillance une option et appuyez sur Enter pour voir les pilotes pré-noyau chargés par grub et les paramètres de démarrage passés par grub au noyau lors de son démarrage :

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

grub-menu.sh n'a qu'une seule option à modifier :

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

Définissez la valeur sur true (cacher les entrées supplémentaires) ou false (liste de toutes les entrées).

Le format par défaut peut être remplacé en appelant le script en utilisant :

grub-menu.sh short

ou :

grub-menu.sh long

Le code :

#!/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: 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="${Currext%%\'*}"
        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

12voto

Exactement cela m'a ennuyé pendant plus d'un an - donc j'ai fait un script rapide et sale pour le faire. J'espère que cela aidera les autres ?

Cela empile les noms dans une file d'attente push/pop, mais pas l'indexation du menu, donc cela pourrait être mieux, mais j'ai été aussi loin que je pouvais le faire.

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

Vous pouvez voir ici une capture d'écran de ma boîte montrant qu'il fonctionne. enter image description here

Comme cela a été demandé dans un commentaire de 2019/8 j'ai mentionné ci-dessus faire un "temp boot". Cette idée était ce qui a commencé à l'origine mon script, et la méthode de démarrage temporaire est venu d'un autre post et il va quelque chose comme ceci.

  1. Définir GRUB_DEFAULT à GRUB_DEFAULT=saved # vi /etc/default/grub
  2. Mettre à jour la configuration de Grub dans /boot # sudo update-grub
  3. Définir le système d'exploitation par défaut à charger (il sera chargé à chaque fois que vous redémarrez la machine) # sudo grub-set-default 0
  4. Lorsqu'il est nécessaire de charger un autre OS (le numéro est un numéro de menu de l'OS comme dans /boot/Grub/Grub.cfg, ceci chargera l'autre OS une seule fois lors du prochain redémarrage - le redémarrage doit être lancé manuellement) : # sudo grub-reboot 4

Réf : https://ubuntuforums.org/showthread.php?t=1310463

9voto

DanMan Points 247

Je viens de découvrir que vous pouvez utiliser l'auto-complétion (en appuyant sur tab deux fois) sur des commandes comme grub-reboot o grub-set-default et vous obtiendrez une liste des entrées disponibles dans le menu de démarrage. Vous pouvez alors simplement copier le titre que vous voulez littéralement, vous n'avez pas besoin d'utiliser un numéro.

Malheureusement, pour une raison quelconque, mon installation de Windows 7 ne s'affiche pas de cette façon.

6voto

Cela devrait être la bonne "chaîne"...

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

Le dernier tuyau supprime les espaces blancs au début de chaque ligne et corrige la séquence des numéros conformément à la saisie des numéros de Grub. Exemple de sortie :

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

Si vous souhaitez voir toutes les entrées, y compris les entrées avancées, vous pouvez utiliser la méthode suivante

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

mais la séquence de chiffres n'est pas adaptée à une utilisation avec Grub-set-default.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X