Fedora 30&31 Bootumstellung führt zu Startproblem

Eigentlich wollte ich was von Endlosschleifen sagen, aber das trifft es nicht, auch wenn eine Schleife als Folge möglich ist. Neulich habe ich auf Fedora 30 Updaten müssen, dabei gab es eine Reihe von Pannen, bei deren Lösung Ihr ab sofort hier nachschlagen könnt.

Die Umstellung auf BLS

Schuld ist die BLS Umstellung in Grub, die zu einigen Verwirrungen und Irrungen geführt hat. Natürlich hat das Suchen mal wieder deutlich mehr Zeit in Anspruch genommen, als das Beheben des resultierenden Problems. Wer rechnet schon mit einer bis Dato unbekannten Bootmichtodschleife? Zugegeben, in meinem Spezialfall war es mehr Tod als Schleife, aber ohne viel Fantasie kann man auch eine Schleife damit bauen.

Die BootLoader Specification kurz BLS kann man an einem passenden Eintrag in der /etc/defult/grub erkennen:

# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DEFAULT=saved

GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT=“gfxterm“
GRUB_ENABLE_BLSCFG=true

Ich hab ein bisschen was weggelassen, damit es leserlicher wird. Wenn BLS aktiv ist, habt Ihr die Booteinträge nicht mehr in der grub2.cfg stehen, sondern hier:

# ls -la /boot/loader/entries/
insgesamt 16
4 -rw-r–r–. 1 root root 379 28. Nov 00:19 7e390913b33b4e5ba8f960a9ba97aeee-0-rescue.conf
4 -rw-r–r–. 1 root root 249 22. Nov 00:15 7e390913b33b4e5ba8f960a9ba97aeee-5.3.12-200.fc30.x86_64.conf
4 -rw-r–r–. 1 root root 249 26. Nov 00:28 7e390913b33b4e5ba8f960a9ba97aeee-5.3.13-200.fc30.x86_64.conf
4 -rw-r–r–. 1 root root 249 2. Dez 17:22 7e390913b33b4e5ba8f960a9ba97aeee-5.3.14-200.fc30.x86_64.conf

Diese Änderung unterstütze ich voll und ganz, da muß man keine unnötigen rebuilds der grub.cfg machen. Einfach neues File rein, oder altes raus. Fertig. Soweit, so gut.

Die Probleme zeigen sich jetzt bei diesem Punkt: „/etc/grub.d/08_fallback_counting“  Da wird mitgezählt, ob wir einen funktionierenden Boot hatten, oder nicht. Wenn der Rechner z.b. beim Boot nicht hochkommt, wird automatisch ein anderer Kernel benutzt, als zuletzt zum Booten eingestellt war. Im Idealfall behebt sich ein Bootproblem somit von allein.

An sich wäre das ok, wenn genau dieser Algorithmus auch sauber funktionieren würde, tut er aber nicht.

Prämisse: Der Rechner bootet nicht durch, Ihr wählt im Kernelmenü einen anderen Kernel aus.

Wenn man den 08-Fallbackcode liest, stellt man fest, daß im Fall der Erkennung des „nicht sauber gebootet“ Zustands, die Auswahl des Kernels, die man selbst gemacht hat, mit dem Defaultwert 1 überschrieben wird. „1“ meint hier den Kernel-Index 1, also den Kernel an Position 2 in der Liste!

insmod increment
# Check if boot_counter exists and boot_success=0 to activate this behaviour.
if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then
   # if countdown has ended, choose to boot rollback deployment,
   # i.e. default=1 on OSTree-based systems.
   if [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then
      set default=1
      set boot_counter=-1
      # otherwise decrement boot_counter
   else
      decrement boot_counter
   fi
   save_env boot_counter
fi

Und bei der „set default=1“ Zeile liegt das Problem, denn was da Index 1 ist als Kernel, ist nicht definiert.

Das Fallbackproblem ist auch dann wirksam, wenn man kein BLS aktiv hat. In diesem Fall läßt es sich besser nachvollziehen, deswegen setzen ich das jetzt mal voraus. Die grub.cfg könnte dann so aussehen:

### BEGIN /etc/grub.d/08_fallback_counting ###
insmod increment
# Check if boot_counter exists and boot_success=0 to activate this behaviour.
if [ -n "${boot_counter}" -a "${boot_success}" = "0" ]; then
  # if countdown has ended, choose to boot rollback deployment,
  # i.e. default=1 on OSTree-based systems.
  if  [ "${boot_counter}" = "0" -o "${boot_counter}" = "-1" ]; then
    set default=1
    set boot_counter=-1
  # otherwise decrement boot_counter
  else
    decrement boot_counter
  fi
  save_env boot_counter
fi
### END /etc/grub.d/08_fallback_counting ###

BEGIN /etc/grub.d/10_linux ###
menuentry 'Fedora (5.3.14-200.fc30.x86_64) 30 (Thirty)' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.3.14-200.fc30.x86_64-advanced-dca7eea1-687e-476a-a9a0-c41ef0329113' {
...
}
menuentry 'Fedora (5.3.13-200.fc30.x86_64) 30 (Thirty)' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.3.13-200.fc30.x86_64-advanced-dca7eea1-687e-476a-a9a0-c41ef0329113' {
...
}
menuentry 'Fedora (5.0.17-200.fc29.x86_64) 30 (Thirty)' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.0.17-200.fc29.x86_64-advanced-dca7eea1-687e-476a-a9a0-c41ef0329113' {
...
}

Das ergibt :

Kernel-Index=0 => „5.3.14-200.fc30.x86_64“
Kernel-Index=1 => „5.3.13-200.fc30.x86_64“
Kernel-Index=2 => „5.0.17-200.fc29.x86_64“

Merke, in dem Fallback steht 1 als Fallbackoption drin.

Das Xen Problem

Wenn jetzt die neueren Kernels von Fc30 nicht bootet, weil die z.b. in einer XenUmgebung laufen, wo ein alter pyGrub Bootloader am werkeln ist, dann funktioniert der Boot nicht. d.b. der nächste Boot funktioniert auch nicht, weil die Fallbackoption auf einen Kernel zurückgreift, der auch nicht funktioniert.

Wenn man jetzt in der grubenv den Kernel-Index=2 ausgesucht hat, z.b. so „saved_entry=Fedora (5.0.17-200.fc29.x86_64) 30 (Thirty)„, dann wird dies wie oben beschrieben ignoriert, weil der FallBackcode nach dem Defaultkernelcode in der Grub.cfg kommt.

Ihr könnt auch tausendmal auswählen, daß Ihr den Kernel haben wollt, ist egal, wird auch überschrieben.

Die Lösung

Da hilft nur eine Aktion: „set default=2“ in die grub.cfg schreiben. Das wird natürlich beim nächsten Kernelinstall übergenagelt, aber a) könnt Ihr das auch in der /etc/grub.d/08-…. anpassen, dann bleibt es erhalten und b) in obiger Prämisse rebootet Ihr eh nicht 😉 hauptsache das System kommt überhaupt hoch.

Jetzt muß keiner glauben, daß das Problem unbekannt wäre, es gibt Bugreports dazu von Fedora 30 Tage 1 an. Weil das Problem für Xen als Bugreport bekannt war, wurde die Upgraderoutine so umgeschrieben, daß BLS deaktiviert ist, wenn Xen als Host gefunden wird. Das alleine schützt aber nicht vor dem Fallbackproblem.

Grubby

Das nächste Problem: grubby. Grubby ist das kleine Shelltool, daß die Grubenv erzeugt, wenn z.b. sagt, welchen Kernel man als Default haben will, Ihr erinnert euch: Grubby: wie man wieder einen Default Kernel setzen kann.

Tja leider ist Grubby wohl nicht ganz mitgekommen und schreibt BLS Kernelinformationen in die grubenv, auch wenn BLS abgeschaltet ist. Da könnt Ihr nur von Hand eingreifen und die grubenv manuell beheben. Aber achtet auf die 1024 Zeichenlänge der grubenv, die muß erhalten bleiben!

Kleines Update:

Wenn man jetzt so danach googelt, findet man jede Menge Hinweise, daß bei dem Upgradeprozess etwas schief gehen wird. Ich komme mehr und mehr zu dem Schluß, daß es eine ganz schlecht geplante Aktion war.

Anstelle von Grubby für den Kerneleintrag zubenutzen, kann man auch folgendes machen:

grub2-editenv /boot/grub2/grubenv set „saved_entry=Fedora (5.3.13-200.fc30.x86_64) 30 (Thirty)“

Natürlich mit dem Kerneleintrag den Ihr wollt 😉

Wie kommt man an diese Bezeichnung?

grep ^menuentry /boot/grub2/grub.cfg | cut -d „‚“ -f2

kommt dies bei raus:

Fedora (5.3.15-200.fc30.x86_64) 30 (Thirty)
Fedora (5.3.14-200.fc30.x86_64) 30 (Thirty)
Fedora (5.3.13-200.fc30.x86_64) 30 (Thirty)
Fedora (0-rescue-9aa92939e4c644e6aa3e09cc4c2311e8) 30 (Thirty)

Jetzt braucht Ihr den Titel nur noch zu kopieren und an den grub2-editenv zu übergeben.

Grubby: wie man wieder einen Default Kernel setzen kann

Ihr habt ein Kernel Update eingespielt bekommen, aber der Default-Kernel ist immer noch der „alte“ Kernel? Willkommen in der digitalen Steinzeit der Grubby Bugs.

Wie man einen Default Kernel setzen kann

Per Mail erreichte mich eine Anfrage zu Grubby, das ist das kleine Tool, das sich um die Grub Booteinträge kümmert. In der Anfrage ging ein Kernel-Update schief und der Default Kernel lies sich nicht setzen. Die Ursache liegt in einem „Steinzeit“-Fehler: Der Grubenv Block ist wie in Stein gemeiselt genau 1024 Bytes lang, egal was sinnvolles drin steht 🙂

Jetzt ist der Bug an sich nichts neues, da reden der Redhat Support, die Fedora Maintainer und die Grubby Devs gefühlt schon eine Ewigkeit drüber. In etlichen Bugreports gibt es einen gemeinsamen Nenner: Grubby und nicht 1024 Bytes große grubenv Dateien 🙂

Wenn man jetzt versucht einen Default-Kernel zu setzen, kann man Opfer dieses Bugs werden und keiner sagt es einem, außer der schon gehässigen Regelmäßigkeit, mit der der alte Kernel gebootet wird. Beispiel:

[root@eve]# grubby --default-kernel
/boot/vmlinuz-5.2.7-100.fc29.x86_64
[root@eve]# grubby --set-default=/boot/vmlinuz-5.2.11-100.fc29.x86_64
[root@eve]# grubby --default-kernel
/boot/vmlinuz-5.2.7-100.fc29.x86_64
[root@eve]# cat /boot/grub2/grubenv
# GRUB Environment Block
saved_entry=Fedora (5.2.7-100.fc29.x86_64) 29 (Twenty Nine)
"

[root@eve#

Die Methode mit der man den Kernel als Default setzen will, spielt dabei keine Rolle:

[root@eve]# grubby --set-default-index=0
grub2-editenv: Fehler: Environment-Block ist zu klein.

Aber immerhin gibt es hier den Hinweis, der Block ist zu klein? Wie kann das sein, da steht doch min. der ALTE Kernel auch drin, wie kann der sich nur durch eine Nummer unterscheidene neue Kernel da nicht auch reinpassen?

Weil da wer von Hand rumgefummelt hatte …

Ja, ich gebs zu, ich habe mal irgendwann den Kernel von Hand da eingetragen, aber das war noch zu 4.20er Zeiten und seit dem gings doch auch, sonst wärs ja nicht 5.2.7 geworden. Die mögliche Antwort ist wenig schmeichelhaft: Grubby ist nicht ganz deterministisch veranlagt in letzter Zeit. Ich erwähnte ja, daß sich die Devs und Maintainer schon länger damit rumquälen, mal gehts, mal gehts nicht mehr. Die Bugreporter sind entsprechend genervt. Die Codebasis von Grubby will ich wohl besser nicht sehen.

Egal, eine Lösung muß her

Also, Ursache ist, daß Grubby nur dann das File erzeugt, wenn es GENAU 1024 Bytes lang ist. Keine Ahnung wieso und ich will es auch nicht wissen…. doch will ich, aber werde ich wohl trotzdem nie erfahren.

Sofern nichts außer dem Kernel in dem grubenv File steht, ist der Fix besonders einfach:

wahlweise mit EFI oder ohne :

rm -f /boot/grub2/grubenv
rm -f /boot/efi/EFI/fedora/grubenv

und dann den Block neu erzeugen lassen:

grubby –set-default-index=0

Fixed. Kniffliger wird es, wenn da noch andere Variablen drinstehen, denn dann dürft Ihr ungelogen mit einem Texteditor die Datei auf genau die 1024 Bytes trimmen/padden und dann abspeichern. Danach sollte grubby auch wieder den Default-Kernel da rein schreiben können.

Achtung:

ggf. sind /boot/grub2/grubenv und /boot/efi/EFI/fedora/grubenv  durch einen Symlink verbunden, schaut Euch das bitte vorher von Hand an, bevor Ihr Euch in Sicherheit wiegt. Es ist Eure Bootconfiguration, also lasst Vorsicht walten 😉 Bei Fragen, welche Datei zuständig ist, wendet Euch an die örtliche LUG, die freuen sich über Zulauf 🙂