Ubuntu VPS: Kernel für den nächsten Start festlegen
GRUB_DEFAULT bleibt im Ubuntu-Cloud-Image wirkungslos. Prüfen Sie echte Menüeinträge und setzen Sie den nächsten Kernel, ohne eine Rettungskonsole zu riskieren.
Welche Datei entscheidet, welchen Kernel Ihre VPS als Nächstes startet
Welche Kernelversion Ihre VPS beim nächsten Start verwendet, wird durch eine generierte Datei festgelegt: /boot/grub/grub.cfg. Diese Datei bearbeiten Sie nie direkt. Sie bearbeiten ihre Eingabedateien und generieren sie anschließend neu. Bei einem Ubuntu-Cloud-Image stammt eine dieser Eingaben vom Image-Anbieter. Dadurch kann die Auswahl im Bootmenü bedeutungslos werden. Deshalb ändern GRUB_DEFAULT=1 und anschließend update-grub auf einem gemieteten Server nichts, während dieselben beiden Schritte bei einer Laptop-Installation funktionieren.
Gehen Sie in dieser Reihenfolge vor. Prüfen Sie, ob Sie den Kernel selbst auswählen können. Lesen Sie jede Eingabedatei, einschließlich der vom Anbieter hinzugefügten Dateien. Lesen Sie die generierte Ausgabedatei und zählen Sie die Einträge, die sie tatsächlich enthält. Wählen Sie erst danach eine Methode zum Festlegen einer Kernelversion. Wenn Sie dies auf einem Rechner falsch machen, den Sie nur über SSH erreichen, benötigen Sie eine Rettungskonsole. Deshalb stehen die sichersten Antworten am Ende dieser Seite. In vielen Fällen sind sie die richtige Wahl.
Zuerst prüfen, ob der Kernel von Ihnen verwaltet wird
uname -r
systemd-detect-virt
ls -1 /boot/vmlinuz-*systemd-detect-virt, kvm, qemu oder xen auszugeben bedeutet, dass Sie einen eigenen Kernel verwenden und alle folgenden Schritte gelten. Gibt das System lxc oder openvz aus, verwendet Ihr Server den Kernel des Hosts. Sie haben dann keinen eigenen Bootloader und können keinen Kernel festlegen. In diesem Fall meldet uname -r eine Version, die in /boot/vmlinuz-* überhaupt nicht erscheint. Der laufende Kernel gehört dem Host. Keine Einstellung auf Ihrer Festplatte kann ihn ändern.
ls -1 /boot/vmlinuz-* enthält die tatsächliche Liste der Kernel, zwischen denen Sie wählen können. Enthält die Liste nur eine Zeile, wurde der vorherige Kernel bereits gelöscht. Keine Bootloader-Einstellung kann ihn zurückbringen. Das geschieht normalerweise während eines autoremove. Sie sollten diesen Vorgang verstehen, bevor Sie auf einem wichtigen System alte Kernel unter Ubuntu bereinigen.
Die von Ihnen bearbeitete Datei ist nicht die Datei, die GRUB einliest
/etc/default/grub enthält einfache Zuweisungen von Shell-Variablen. Diese Datei dient als Eingabe. /boot/grub/grub.cfg ist die Ausgabe. Sie beginnt mit # DO NOT EDIT THIS FILE und der Begründung. Alles, was Sie in die Ausgabedatei schreiben, geht verloren, sobald ein Kernel-Paket installiert oder entfernt wird, weil die Paketskripte die Datei neu erzeugen.
cat /usr/sbin/update-grubupdate-grub ist ein Wrapper. Er führt grub-mkconfig -o /boot/grub/grub.cfg aus. Dieses liest die Variablen ein, führt jedes Skript in /etc/grub.d/ aus und schreibt das Ergebnis. Zwei Befehle, eine Richtung: Die Eingaben gehen hinein, grub.cfg kommt heraus.
Was Ihre Einstellung überschreibt: /etc/default/grub.d
grep -rn '^[^#]' /etc/default/grub /etc/default/grub.d/Der zweite Pfad ist der Teil, den viele übersehen. grub-mkconfig liest zuerst /etc/default/grub ein, danach jede *.cfg-Datei in /etc/default/grub.d/ in der Reihenfolge der Glob-Sortierung. Sehen Sie sich den Code an, der dies umsetzt:
grep -n 'default/grub' /usr/sbin/grub-mkconfigDas Einlesen erfolgt als normales Shell-Skript. Daher gilt die letzte Zuweisung. Ubuntu-Cloud-Images enthalten Dateien in diesem Verzeichnis. Diese setzen beispielsweise das Timeout und die Kernel-Befehlszeile, nachdem Ihre Datei bereits eingelesen wurde. Ihr GRUB_TIMEOUT=10 in /etc/default/grub wird kurz danach von einer Herstellerdatei überschrieben, die den Wert auf 0 setzt. Der obige grep-Befehl gibt die tatsächlichen Zuweisungen auf Ihrem Image aus. Verwenden Sie daher diese Ausgabe, statt sich auf diesen Satz zu verlassen.
Daraus folgt die praktische Regel: Legen Sie Ihre eigenen Einstellungen in einer Datei ab, die zuletzt sortiert wird, beispielsweise /etc/default/grub.d/99-local.cfg, statt /etc/default/grub zu bearbeiten. Dann kann keine vom Image bereitgestellte Datei danach eingelesen werden.
Warum GRUB_FORCE_PARTUUID die Menüauswahl irrelevant macht
grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/
grep -n GRUB_FORCE_PARTUUID /etc/grub.d/10_linux
sudo grep -n 'root=PARTUUID' /boot/grub/grub.cfgGRUB_FORCE_PARTUUID weist den Generator an, das Root-Dateisystem anhand der Partitions-UUID zu finden. Dieser Wert wird direkt als root=PARTUUID=... in die Kernel-Befehlszeile geschrieben, statt beim Booten nach einer Dateisystem-UUID zu suchen. Der Image-Anbieter setzt diese Variable, weil ein einziges Disk-Image dadurch zuverlässig auf Hardware bootet, für die es nicht erstellt wurde. Der zweite grep-Befehl zeigt den Code, der die Variable auswertet, in /etc/grub.d/10_linux. Dieses Skript liegt auf Ihrer eigenen Festplatte. Es ist maßgeblich dafür, wie sich Ihr Image verhält.
Hier ist die Konsequenz entscheidend: Auf diesem Pfad schreibt der Generator einen direkten Boot-Eintrag statt einer vollständigen Liste der installierten Kernel. Zählen Sie, wie viele Einträge tatsächlich vorhanden sind.
sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg
sudo grep -nE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfgWenn die Anzahl 1 ist, gibt es keinen zweiten Eintrag zur Auswahl. GRUB_DEFAULT=1 verweist dann auf einen Eintrag, der nicht existiert. GRUB kann ihn nicht auflösen und bootet deshalb den ersten Eintrag. Das ist der neue Kernel, den Sie vermeiden wollten. grub-set-default hilft ebenfalls nicht, weil nicht der Standardwert das Problem ist. Das Menü, aus dem Sie auswählen möchten, wurde nie erzeugt.
Um wieder ein vollständiges Menü zu erhalten, verschieben Sie die Datei des Anbieters und prüfen Sie das Ergebnis, bevor Sie die Änderung übernehmen. grub-mkconfig ohne -o schreibt die Ausgabe nach stdout und verändert nichts auf der Festplatte.
sudo grub-mkconfig 2>/dev/null | grep -cE '^\s*(menuentry|submenu) '
sudo mkdir -p /root/grub-backup
sudo mv /etc/default/grub.d/<the file your grep named> /root/grub-backup/
sudo grub-mkconfig 2>/dev/null | grep -cE '^\s*(menuentry|submenu) 'Wenn die Anzahl von 1 auf mehrere Einträge steigt, erscheinen die Einträge, sobald die Erzwingung entfernt wurde. Bisher wurde noch nichts geschrieben. Stellen Sie die Datei wieder her, wenn die zweite Zählung nicht korrekt aussieht. Die erzwungene PARTUUID ist die Methode, mit der das Image Ihres Providers sein Root-Dateisystem findet. Wenn Sie sie entfernen, verwendet das System stattdessen den Suchpfad. Erstellen Sie einen Snapshot, bevor Sie update-grub tatsächlich ausführen.
Wenn Sie nur einen einzelnen fehlerhaften Kernel überstehen müssen, beenden Sie die Änderungen hier und verwenden Sie die weiter unten beschriebenen sichereren Optionen. Auf einem entfernten Server das Bootmenü neu zu erstellen, um ein einzelnes Upgrade zu umgehen, ist riskanter, als das Problem rechtfertigt.
Warum Eintragsnummern zum Fixieren ungeeignet sind
GRUB_DEFAULT akzeptiert eine Nummer, einen Titel oder einen Bezeichner. Nummern zählen Einträge der obersten Ebene ab 0. Ein verschachtelter Eintrag verwendet > als Trennzeichen. GRUB_DEFAULT="1>2" bezeichnet daher den Eintrag mit dem Index 2 im Untermenü mit dem Index 1.
Indizes ändern sich. 10_linux listet Kernel in absteigender Reihenfolge auf. Durch die Installation eines Kernels rutscht jeder ältere Eintrag um eine Position nach unten. Durch das Entfernen eines Kernels rücken sie wieder nach oben. Auch Ihr sorgfältig gewähltes 1>2 wird danach weiterhin aufgelöst. Es bezeichnet nun einen anderen Kernel. Es tritt kein Fehler auf und es erscheint keine Warnung. Sie bemerken das erst nach einem Reboot.
Bezeichner ändern sich nicht, weil jeder die Kernel-Version enthält. Lesen Sie Ihre Bezeichner aus:
sudo awk -F"'" '/menuentry_id_option/ {print $2, "==>", $4}' /boot/grub/grub.cfgIgnorieren Sie die ersten Zeilen der Ausgabe. Sie enthalten die Variable, die im Header definiert wird. Danach steht links der für Leser sichtbare Titel und rechts der Bezeichner, den Sie an die Tools übergeben. Bei einem Eintrag in einem Untermenü verbinden Sie den Bezeichner des Untermenüs und den Bezeichner des Eintrags mit >, in genau dieser Reihenfolge. Das entspricht der numerischen Form.
Starten Sie den vorherigen Kernel einmalig mit grub-reboot
Eine einmalige Auswahl ist auf einem Remote-Server die richtige Vorgehensweise, weil sie sich selbst zurücksetzt. grub-reboot schreibt next_entry in /boot/grub/grubenv. GRUB liest diese Variable, löscht sie und speichert den gelöschten Wert, bevor es irgendetwas startet. Dadurch wird ein Kernel, der eine Panic auslöst, beim nächsten Boot nicht erneut versucht. Sie haben einen Versuch. Danach verwendet die Maschine selbstständig wieder den normalen Standard.
Prüfen Sie zunächst, ob Ihre generierte Konfiguration diese Variable überhaupt liest:
sudo grep -n -B2 -A5 'next_entry' /boot/grub/grub.cfgSie sollten eine Zeile mit load_env und einen Block sehen, der default aus next_entry setzt. Gibt grep nichts aus, liest Ihr Image grubenv beim Boot nicht. Dann wird grub-reboot zwar in der Shell akzeptiert, vom Bootloader aber ignoriert. Das ist derselbe erzwungene direkte Bootpfad aus dem vorherigen Abschnitt, der an einer zweiten Stelle auftritt.
sudo grub-reboot '<the identifier you copied>'
sudo grub-editenv listgrub-editenv list sollte nun eine Zeile mit next_entry= ausgeben, die exakt den von Ihnen übergebenen Wert enthält. Öffnen Sie die Konsole Ihres Providers in einem Browser-Tab. Starten Sie die Maschine anschließend neu und prüfen Sie das Ergebnis.
sudo rebootuname -rWenn uname -r die ältere Version meldet, war die Auswahl erfolgreich. Wird die neue Version gemeldet, konnte entweder die Kennung nicht aufgelöst werden oder grubenv wird nicht gelesen. In beiden Fällen ist die Maschine wieder erreichbar. Genau das ist der Zweck der einmaligen Auswahl.
Die Auswahl mit GRUB_DEFAULT=saved dauerhaft festlegen
GRUB_DEFAULT=saved bezieht den Standardwert aus saved_entry in grubenv. Diesen Wert setzen Sie mit grub-set-default. Die Einstellung bleibt auch bei Kernel-Installationen erhalten, weil update-grub grub.cfg neu schreibt und grubenv nicht verändert.
echo 'GRUB_DEFAULT=saved' | sudo tee /etc/default/grub.d/99-local.cfg
sudo update-grub
sudo grub-set-default '<the identifier you copied>'
sudo grub-editenv list
sudo grep -n 'set default' /boot/grub/grub.cfgDer letzte Befehl muss set default="${saved_entry}" ausgeben. Wird set default="0" ausgegeben, hat eine nach Ihrer Datei geladene Quelldatei GRUB_DEFAULT wieder auf einen festen Wert gesetzt. Listen Sie daher /etc/default/grub.d/ erneut auf und prüfen Sie, ob 99-local.cfg tatsächlich zuletzt sortiert wird.
GRUB_SAVEDEFAULT=true ist eine andere Einstellung und wird leicht mit dieser verwechselt. Sie speichert den Kernel, mit dem Sie gerade gestartet haben, als neuen Standard. Der Standardwert folgt dadurch dem letzten erfolgreichen Bootvorgang. Auf einem Server kann ein unbeaufsichtigter Reboot den festgelegten Kernel dadurch unbemerkt ändern. Lassen Sie die Einstellung deaktiviert, sofern Sie genau dieses Verhalten nicht benötigen.
Eine Auswahl anhand der Kennung kann dennoch auf eine bestimmte Weise fehlschlagen. Entfernen Sie den Kernel, auf den die Kennung verweist, kann die Kennung nicht mehr aufgelöst werden. Dadurch fällt die Auswahl auf den ersten Eintrag zurück. Halten Sie daher auch das Paket zurück oder schließen Sie diesen Kernel von autoremove aus.
Das Menü auf der Provider-Konsole anzeigen
Für eine interaktive Auswahl muss das Menü auf dem Bildschirm angezeigt werden. Cloud-Images blenden es aus. Tragen Sie diese Einstellungen in die Datei ein, die zuletzt verarbeitet wird, und führen Sie anschließend sudo update-grub aus.
GRUB_TIMEOUT=10
GRUB_TIMEOUT_STYLE=menu
GRUB_RECORDFAIL_TIMEOUT=10GRUB_TIMEOUT_STYLE=hidden zusammen mit GRUB_TIMEOUT=0 zeigt überhaupt nichts an. Eine Person, die die Konsole beobachtet, sieht dann sofort Kernel-Meldungen und schließt daraus, dass der Bootloader übersprungen wurde. GRUB_RECORDFAIL_TIMEOUT ist das separate Timeout für den Fall, dass ein Bootvorgang nicht abgeschlossen wurde. Cloud-Images setzen auch diesen Wert auf 0. Deshalb hält ein Server, dessen Bootvorgang gerade fehlgeschlagen ist, ebenfalls nicht an und wartet auf Ihre Eingabe.
Wenn Ihr Provider statt einer grafischen Konsole eine serielle Konsole bereitstellt und Sie weiterhin nichts sehen, schreibt GRUB auf ein Terminal, das für Sie nicht sichtbar ist. Fügen Sie beide Zeilen gemeinsam hinzu. Die erste wählt die Ausgaben aus, die zweite konfiguriert den Port:
GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"Ab jetzt werden jedem Bootvorgang zehn Sekunden hinzugefügt. Setzen Sie das Timeout nach Abschluss der Arbeiten wieder auf 0.
Sicherere Optionen als das Bearbeiten des Bootloaders
Die Eingabe im Bootloader auf einem Rechner zu ändern, auf den Sie nur über SSH zugreifen, ist die riskanteste Option auf dieser Seite. Es gibt einfachere Lösungen. Sie beheben normalerweise das eigentliche Problem.
Kernel-Pakete zurückhalten. Wenn Sie verhindern möchten, dass ein neuerer Kernel installiert wird, teilen Sie das dem Paketmanager mit und nicht dem Bootloader.
apt list --installed 2>/dev/null | grep -E '^linux-(image|headers|generic|virtual|kvm|aws|azure|gcp|oracle)'
sudo apt-mark hold linux-image-virtual linux-headers-virtual
apt-mark showholdVerwenden Sie die Namen, die der erste Befehl ausgegeben hat, da Cloud-Images häufig die Variante virtual oder kvm statt generic installieren. Ein zurückgehaltenes Paket wird von apt upgrade übersprungen. Der Befehl meldet dies mit The following packages have been kept back:. Auch unbeaufsichtigte Upgrades unter Ubuntu überspringen das Paket. Die Auswirkungen sind erheblich: Ein zurückgehaltener Kernel erhält keine Sicherheitsupdates mehr. Betrachten Sie dies daher als zeitlich begrenzte Pause und geben Sie das Paket mit sudo apt-mark unhold wieder frei. Wenn Sie Kernel-Updates vermeiden, weil Reboots Ausfallzeit verursachen, und nicht weil ein bestimmter Kernel fehlerhaft ist, ist Live-Kernel-Patching auf einem VPS die passende Lösung.
Erstellen Sie vor dem Upgrade einen Snapshot. Ein Snapshot lässt sich innerhalb weniger Minuten wiederherstellen. Sie müssen dabei nichts über die Konsole eingeben. Außerdem besteht keine Gefahr, dass eine Änderung am Bootloader nur teilweise angewendet wird. Erstellen Sie den Snapshot, führen Sie das Upgrade durch, starten Sie den Server neu und prüfen Sie ihn. Wenn der neue Kernel Probleme verursacht, machen Sie den Snapshot rückgängig. Der Bootpfad entspricht dann exakt dem vorherigen Zustand.
Verwenden Sie bei einem bereits ausgefallenen Server die Konsole oder ein Rettungs-Image. Wenn der Server nicht mehr bootet, beheben Sie das Problem nicht in der Bootloader-Konfiguration. Dieser Wiederherstellungsweg ist ein eigenes Verfahren: Vorgehen, wenn ein VPS nach einem Kernel-Update nicht mehr bootet.
Was fehlschlägt und welche Meldung Sie sehen
Ihre Änderung an /boot/grub/grub.cfg ist verschwunden. Ein Kernelpaket wurde installiert oder entfernt, sein Maintainer-Skript wurde mit update-grub ausgeführt, und die Datei wurde aus den Eingabedateien neu erzeugt. Der Header # DO NOT EDIT THIS FILE nennt die beiden Speicherorte der Eingabedateien. Bearbeiten Sie diese Dateien.
grub-editenv: error: environment block too small. /boot/grub/grubenv fehlt oder ist abgeschnitten. Erstellen Sie die Datei mit sudo grub-editenv /boot/grub/grubenv create neu, setzen Sie anschließend Ihren Wert erneut und prüfen Sie ihn mit sudo grub-editenv list.
Ein festgelegter Kernel löst mit VFS: Unable to mount root fs on unknown-block(0,0) einen Kernel-Panic aus. Der festgelegte Eintrag verweist auf einen Kernel oder eine initrd, die nicht mehr auf dem Datenträger vorhanden ist. Ursache ist meist, dass das Paket entfernt wurde, während die Kennung in grubenv erhalten blieb. Starten Sie zur Wiederherstellung über die Konsole einen funktionierenden Eintrag und löschen Sie anschließend den veralteten Wert.
uname -r ist nach einem erwarteten Reboot unverändert. Prüfen Sie drei Punkte in dieser Reihenfolge: Zeigt grub-editenv list weiterhin Ihren Wert an oder wurde er bereits verarbeitet? Erscheint die von Ihnen gesetzte Kennung in der aktuellen grub.cfg? Enthält grub.cfg eine set default-Zeile, die die von Ihnen gesetzte Variable ausliest? Einer dieser drei Punkte erklärt das Verhalten.
Das Menü wurde nach einem Absturz selbstständig angezeigt. GRUB speichert einen fehlgeschlagenen Boot in grubenv als recordfail=1. Dadurch wird das Menü beim folgenden Boot erzwungen, damit ein Benutzer eingreifen kann. Löschen Sie den Wert mit sudo grub-editenv /boot/grub/grubenv unset recordfail, sobald das System wieder ordnungsgemäß arbeitet.
Der wichtigste Satz lautet: Die Datei, die Sie bearbeiten, ist nicht die Datei, die GRUB einliest. Bei einem Cloud-Image liegt genau in dieser Differenz die Ursache der Verwirrung. Lesen Sie zuerst die erzeugte Konfiguration. Jede Entscheidung auf dieser Seite ergibt sich aus ihrem tatsächlichen Inhalt.
FAQ
Warum ändert GRUB_DEFAULT=1 nicht, mit welchem Kernel meine VPS startet?
Bei einem Ubuntu-Cloud-Image enthält die generierte /boot/grub/grub.cfg häufig nur einen einzigen Booteintrag. Index 1 bezeichnet dann keinen Eintrag, und GRUB verwendet den ersten Eintrag. Prüfen Sie dies mit sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg. Eine Anzahl von 1 ist die Erklärung. Ursache ist GRUB_FORCE_PARTUUID. Der Image-Anbieter setzt diese Einstellung in einer Datei unter /etc/default/grub.d/. Dadurch verwendet der Generator einen direkten Bootpfad, statt eine vollständige Liste der installierten Kernel zu erstellen. Ermitteln Sie die Datei mit grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/.
Wie starte ich den vorherigen Kernel genau einmal?
Führen Sie sudo grub-reboot '<identifier>' mit einem Bezeichner aus Ihrer eigenen grub.cfg aus. Starten Sie anschließend neu, während die Provider-Konsole bereits geöffnet ist. GRUB löscht next_entry vor dem Booten. Die Auswahl gilt daher genau für einen Versuch, und ein Kernel mit Panic wird nicht erneut versucht. Prüfen Sie mit sudo grub-editenv list, ob der Wert übernommen wurde. Bevor Sie sich darauf verlassen, führen Sie sudo grep -n next_entry /boot/grub/grub.cfg aus. Ein Image, dessen Konfiguration grubenv nie lädt, ignoriert den Befehl ohne Fehlermeldung.
Sollte ich nach der Eintragsnummer oder nach dem Bezeichner auswählen?
Nach dem Bezeichner. Eintragsnummern sind Positionen in einer Liste, die 10_linux bei jedem Neuaufbau mit dem neuesten Eintrag zuerst erstellt. Deshalb ändern sie sich, sobald ein Kernel installiert oder entfernt wird. Ein veraltetes 1>2 verweist weiterhin auf einen tatsächlich vorhandenen, aber falschen Eintrag. Es gibt keine Warnung. Bezeichner enthalten die Kernelversion. Sie passen daher entweder zum gewünschten Kernel oder lassen sich nicht auflösen. Listen Sie die Bezeichner mit sudo grep -n menuentry_id_option /boot/grub/grub.cfg auf und kopieren Sie die Zeichenfolge in Anführungszeichen, die in jeder Eintragszeile folgt.
Ist es sicherer, das Kernel-Paket zurückzuhalten, als den Bootloader zu ändern?
Für das übliche Ziel: ja. sudo apt-mark hold linux-image-virtual linux-headers-virtual verhindert, dass ein neuerer Kernel überhaupt installiert wird. Dadurch ändert sich der Bootpfad nicht, und eine Konfiguration über eine möglicherweise nicht verfügbare Konsole kann nicht fehlschlagen. Prüfen Sie zunächst mit apt list --installed die auf Ihrem eigenen System installierten Variantenbezeichnungen. Überprüfen Sie die Zurückhaltung anschließend mit apt-mark showhold. Der Nachteil ist, dass ein zurückgehaltenes Kernel-Paket keine Sicherheitsupdates erhält. Legen Sie daher fest, wann Sie sudo apt-mark unhold ausführen, bevor Sie das Paket zurückhalten.