SSD Nodes Learn Hosting plans →
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-28

Ubuntu VPS kernel vastzetten voor volgende boot

GRUB_DEFAULT werkt vaak niet op cloud images. Leer hoe u de juiste menu-items uitleest en de kernel veilig vastzet zonder dat u een rescue console nodig heeft na de reboot.

Wat bepaalt welke kernel uw VPS opstart

Welke kernel uw VPS bij de volgende opstart gebruikt, wordt bepaald door één gegenereerd bestand, /boot/grub/grub.cfg. U bewerkt dit bestand nooit direct. U bewerkt de invoerbestanden en genereert het bestand opnieuw. Bij een Ubuntu-cloudimage is een van deze invoerbestanden afkomstig van de leverancier van de image. Dit kan ervoor zorgen dat menu-selecties irrelevant worden. Daarom veranderen GRUB_DEFAULT=1 gevolgd door update-grub niets op een gehuurde server, terwijl dezelfde twee stappen wel werken op een laptopinstallatie.

Werk in deze volgorde. Bevestig eerst of u zelf de kernel mag kiezen. Lees elk invoerbestand, inclusief de bestanden die door de leverancier zijn toegevoegd. Lees de gegenereerde uitvoer en tel het werkelijke aantal vermeldingen. Kies pas daarna een methode om de kernel vast te pinnen. Als u dit fout doet op een machine die u alleen via SSH kunt bereiken, kost dit u een rescue console. De veiligste antwoorden staan daarom aan het einde van deze pagina en zijn vaak de juiste keuze.

Controleer eerst of de kernel van u is om deze vast te pinnen

uname -r
systemd-detect-virt
ls -1 /boot/vmlinuz-*

systemd-detect-virt Als kvm, qemu of xen wordt getoond, betekent dit dat u uw eigen kernel draait en dat alles hieronder van toepassing is. Als lxc of openvz wordt getoond, betekent dit dat uw server de kernel van de host deelt; u heeft dus geen eigen bootloader en er valt niets vast te pinnen. In dat geval rapporteert uname -r een versie die helemaal niet voorkomt in /boot/vmlinuz-*, omdat de actieve kernel toebehoort aan de host en geen enkele instelling op uw schijf dit kan wijzigen.

ls -1 /boot/vmlinuz-* is de werkelijke lijst met kernels waaruit u kunt kiezen. Als deze slechts één regel bevat, is de vorige kernel al verwijderd en kan geen enkele bootloader-instelling deze terugkrijgen. Dit gebeurt meestal tijdens een autoremove, wat het waard is om te begrijpen voordat u oude kernels op Ubuntu opruimt op een server die voor u van belang is.

Het bestand dat u bewerkt is niet het bestand dat GRUB leest

/etc/default/grub bevat eenvoudige shell-variabeletoewijzingen. Dit is een invoerbestand. /boot/grub/grub.cfg is de uitvoer en begint met # DO NOT EDIT THIS FILE en de reden hiervoor. Alles wat u in de uitvoer schrijft, verdwijnt zodra een kernelpakket wordt geïnstalleerd of verwijderd, omdat de scripts van het pakket het bestand opnieuw genereren.

cat /usr/sbin/update-grub

update-grub is een wrapper. Het voert grub-mkconfig -o /boot/grub/grub.cfg uit, dat de variabelen leest, elk script in /etc/grub.d/ uitvoert en het resultaat wegschrijft. Twee commando's, één richting: invoer gaat erin, grub.cfg komt eruit.

Wat uw instelling overschrijft: /etc/default/grub.d

grep -rn '^[^#]' /etc/default/grub /etc/default/grub.d/

Het tweede pad is het onderdeel dat vaak over het hoofd wordt gezien. grub-mkconfig laadt /etc/default/grub als eerste, gevolgd door elk *.cfg-bestand in /etc/default/grub.d/ in de volgorde van de glob-expressie. Lees de code die dit uitvoert:

grep -n 'default/grub' /usr/sbin/grub-mkconfig

Het laden (sourcing) gebeurt via een standaard shell, dus de laatste toewijzing wint. Ubuntu cloud-images bevatten bestanden in die map die zaken als de timeout en de kernel command line instellen nadat uw bestand al is ingelezen. Uw GRUB_TIMEOUT=10 in /etc/default/grub wordt een moment later overschreven door een leveranciersbestand dat deze op 0 zet. De bovenstaande grep toont de exacte toewijzingen op uw image; vertrouw op die uitvoer in plaats van op deze zin.

De praktische regel is daarom: plaats uw eigen instellingen in een bestand dat als laatste wordt gesorteerd, zoals /etc/default/grub.d/99-local.cfg, in plaats van /etc/default/grub te bewerken. Op die manier kan niets dat door de image wordt meegeleverd, na uw configuratie worden uitgevoerd.

Waarom GRUB_FORCE_PARTUUID de menuselectie irrelevant maakt

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.cfg

GRUB_FORCE_PARTUUID instrueert de generator om het root-bestandssysteem te vinden op basis van de partitie-UUID, direct geschreven op de kernel-commandoregel als root=PARTUUID=..., in plaats van te zoeken naar een bestandssysteem-UUID tijdens het opstarten. De leverancier van de image stelt dit in omdat het ervoor zorgt dat één disk-image betrouwbaar opstart op hardware waarvoor deze niet is gebouwd. De tweede grep toont u de code die op de variabele reageert, in /etc/grub.d/10_linux. Dat script staat op uw eigen schijf en is de autoriteit over wat uw image doet.

De consequentie is hier wat telt: op dat pad schrijft de generator een direct opstartitem in plaats van een volledige lijst met geïnstalleerde kernels. Tel wat u uiteindelijk heeft overgehouden.

sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg
sudo grep -nE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg

Als het aantal 1 is, is er geen tweede item om te selecteren, dus benoemt GRUB_DEFAULT=1 een item dat niet bestaat. GRUB kan dit niet oplossen, dus start het de eerste vermelding op, wat de nieuwe kernel is die u probeerde te vermijden. grub-set-default helpt ook niet, omdat de standaardinstelling niet het defecte onderdeel is. Het menu waaruit u probeert te kiezen, is nooit gegenereerd.

Om een volledig menu terug te krijgen, verplaatst u het bestand van de leverancier en bekijkt u het resultaat voordat u het definitief maakt. grub-mkconfig zonder -o schrijft naar de standaarduitvoer en wijzigt niets op de schijf.

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) '

Een aantal dat springt van 1 naar meerdere betekent dat de items verschijnen zodra de forcering is verwijderd. Er is nog niets geschreven. Plaats het bestand terug als het tweede aantal er niet goed uitziet, omdat de geforceerde PARTUUID de manier is waarop de image van uw provider het root-bestandssysteem lokaliseert, en het verwijderen ervan verplaatst de machine naar het zoekpad. Maak een snapshot voordat u update-grub daadwerkelijk uitvoert.

Als uw enige doel is om één slechte kernel te overleven, stop dan hier en gebruik de veiligere opties verderop. Het opnieuw opbouwen van het opstartmenu op een externe server om aan een enkele upgrade te ontsnappen, is meer risico dan het probleem waard is.

Waarom regelnummers ongeschikt zijn voor pinning

GRUB_DEFAULT accepteert een nummer, een titel of een identifier. Nummers tellen de items op het hoogste niveau vanaf 0. Een genest item gebruikt > als scheidingsteken, dus GRUB_DEFAULT="1>2" betekent het item op index 2 binnen het submenu op index 1.

Indices veranderen. 10_linux toont kernels met de nieuwste bovenaan; het installeren van een kernel schuift elk ouder item één positie naar beneden, en het verwijderen van een kernel schuift ze omhoog. Uw zorgvuldig ingestelde 1>2 wordt daarna nog steeds opgelost. Het verwijst nu echter naar een andere kernel. Er treden geen fouten op, er verschijnen geen waarschuwingen, en u merkt het pas na een herstart.

Identifiers veranderen niet, omdat ze elk de kernelversie bevatten. Lees de uwe uit:

sudo awk -F"'" '/menuentry_id_option/ {print $2, "==>", $4}' /boot/grub/grub.cfg

Negeer de eerste paar regels van de uitvoer; dit zijn de variabelen die in de header worden gedefinieerd. Daarna staat aan de linkerkant de titel die een gebruiker ziet, en aan de rechterkant de identifier die u aan de tools doorgeeft. Voor een item binnen een submenu combineert u de identifier van het submenu en de identifier van het item met >, in die volgorde, precies zoals bij de numerieke notatie.

Start de vorige kernel eenmalig met grub-reboot

Een eenmalige selectie is de juiste keuze op een externe server, omdat deze actie zichzelf ongedaan maakt. grub-reboot schrijft next_entry naar /boot/grub/grubenv. GRUB leest deze variabele, wist deze en slaat de gewiste waarde op voordat het systeem opstart. Hierdoor wordt een kernel die een kernel panic veroorzaakt niet opnieuw geprobeerd bij de volgende opstartpoging. U krijgt één poging, waarna de machine automatisch terugkeert naar de standaardinstelling.

Controleer eerst of uw gegenereerde configuratie deze variabele überhaupt inleest:

sudo grep -n -B2 -A5 'next_entry' /boot/grub/grub.cfg

U zoekt naar een load_env-regel en een blok dat default instelt op basis van next_entry. Als de grep niets uitvoert, leest uw image grubenv nooit in tijdens het opstarten. In dat geval wordt grub-reboot wel geaccepteerd in de shell, maar genegeerd door de bootloader. Dit is hetzelfde geforceerde directe opstartpad uit de vorige sectie dat op een tweede plek opduikt.

sudo grub-reboot '<the identifier you copied>'
sudo grub-editenv list

grub-editenv list zou nu een next_entry=-regel moeten tonen die exact bevat wat u heeft doorgegeven. Open de console van uw provider in een browsertabblad, start de server opnieuw op en controleer het resultaat.

sudo reboot
uname -r

Als uname -r de oudere versie rapporteert, betekent dit dat de pin is geslaagd. Als de nieuwe versie wordt gerapporteerd, is de identifier niet opgelost of wordt grubenv niet ingelezen. In beide gevallen is de machine bereikbaar, wat het doel is van het gebruik van de eenmalige methode.

Maak de keuze permanent met GRUB_DEFAULT=saved

GRUB_DEFAULT=saved zorgt ervoor dat de standaardwaarde wordt geladen vanuit saved_entry in grubenv, en u stelt deze waarde in met grub-set-default. Deze instelling blijft behouden na kernel-installaties, omdat update-grub het bestand grub.cfg herschrijft en nooit grubenv wijzigt.

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.cfg

Het laatste commando moet set default="${saved_entry}" weergeven. Als het set default="0" weergeeft, heeft een script dat na uw bestand wordt uitgevoerd GRUB_DEFAULT teruggezet naar een letterlijke waarde. Vermeld in dat geval /etc/default/grub.d/ opnieuw en controleer of 99-local.cfg daadwerkelijk als laatste wordt gesorteerd.

GRUB_SAVEDEFAULT=true is een andere instelling die gemakkelijk hiermee verward kan worden. Deze optie slaat de laatst opgestarte kernel op als de nieuwe standaard, waardoor de standaardkeuze altijd de laatst succesvolle boot volgt. Op een server betekent dit dat een onbeheerde herstart uw vastgezette keuze ongemerkt kan wijzigen. Laat deze optie uitgeschakeld, tenzij dit het gewenste gedrag is.

Een vastgezette keuze op basis van een identifier kan nog steeds op één manier falen. Als u de kernel verwijdert waarnaar wordt verwezen, kan de identifier niet langer worden opgelost. Hierdoor valt het systeem terug op het eerste item in de lijst. Zet het pakket daarom op 'hold' of zorg ervoor dat de betreffende kernel wordt uitgesloten van autoremove.

Het menu op een providerconsole krijgen

Interactief kiezen vereist dat het menu op het scherm verschijnt, maar cloud-images verbergen dit. Plaats deze instellingen in het bestand dat als laatste wordt gesorteerd en voer daarna sudo update-grub uit.

GRUB_TIMEOUT=10
GRUB_TIMEOUT_STYLE=menu
GRUB_RECORDFAIL_TIMEOUT=10

GRUB_TIMEOUT_STYLE=hidden in combinatie met GRUB_TIMEOUT=0 toont helemaal niets, waardoor iemand die de console bekijkt ziet dat de kernel-berichten direct starten en concludeert dat de bootloader is overgeslagen. GRUB_RECORDFAIL_TIMEOUT is de afzonderlijke time-out die wordt gebruikt na een boot die niet is voltooid; cloud-images zetten deze ook op 0. Dit is de reden waarom een server die niet is opgestart, niet stopt om op uw invoer te wachten.

Als uw provider een seriële console aanbiedt in plaats van een grafische en u ziet nog steeds niets, dan schrijft GRUB naar een terminal die u niet kunt zien. Voeg beide regels samen toe, omdat de eerste de uitvoer selecteert en de tweede de poort configureert:

GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"

Vanaf nu wordt er bij elke boot 10 seconden toegevoegd. Zet de time-out terug naar 0 zodra u klaar bent.

Veiligere opties dan het bewerken van de bootloader

Het wijzigen van de bootloader-input op een machine die u alleen via SSH bereikt, is de optie met het hoogste risico op deze pagina. Er bestaan betere oplossingen en deze lossen meestal het werkelijke probleem op.

Houd de kernel-pakketten vast. Als het doel is "geef mij geen nieuwere kernel", geef dit dan aan bij de pakketbeheerder in plaats van bij de 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 showhold

Gebruik de namen die het eerste commando heeft weergegeven, omdat cloud-images doorgaans de virtual of kvm-variant installeren in plaats van generic. Als de nieuwere kernel verscheen rond een image-verversing en u vermoedt dat de release zelf is gewijzigd, dan is dat niet het geval, want een point release is de updates die u al heeft verwerkt in nieuwe installatiemedia en biedt een reeds gepatchte server niets wat niet weken eerder al werd aangeboden. Een vastgehouden pakket wordt overgeslagen door apt upgrade, die dit aankondigt met The following packages have been kept back:, en het wordt ook overgeslagen door unattended upgrades op Ubuntu. De prijs is reëel: een vastgehouden kernel ontvangt geen beveiligingsupdates meer, dus beschouw het als een pauze met een einddatum en geef het pakket weer vrij met sudo apt-mark unhold. Als u kernel-updates vermijdt omdat reboots downtime kosten in plaats van omdat een specifieke kernel slecht is, biedt live kernel patching op een VPS daarvoor de oplossing.

Maak een snapshot vóór de upgrade. Een snapshot herstelt het systeem binnen enkele minuten, zonder console-invoer en zonder het risico op een half doorgevoerde bootloader-wijziging. Maak een snapshot, upgrade, reboot en verifieer. Als de nieuwe kernel niet naar behoren werkt, draait u de wijziging terug en is het boot-pad exact zoals het was.

Gebruik de console of een rescue-image voor een machine die al offline is. Zodra de server niet meer opstart, is de bootloader-configuratie niet de plek waar u dit herstelt, en dat herstelpad is een eigen procedure: wat te doen als een VPS niet opstart na een kernel-update.

Wat er misgaat en de meldingen die u zult zien

Uw wijziging in /boot/grub/grub.cfg is verdwenen. Er is een kernelpakket geïnstalleerd of verwijderd, het bijbehorende maintainer-script heeft update-grub uitgevoerd en het bestand is opnieuw gegenereerd op basis van de invoer. De # DO NOT EDIT THIS FILE-header benoemt de twee invoerlocaties. Bewerk die bestanden.

grub-editenv: error: environment block too small. /boot/grub/grubenv ontbreekt of is afgebroken. Maak het opnieuw aan met sudo grub-editenv /boot/grub/grubenv create, stel daarna uw waarde opnieuw in en bevestig met sudo grub-editenv list.

Een vastgezette (pinned) kernel veroorzaakt een kernel panic met VFS: Unable to mount root fs on unknown-block(0,0). Het item dat u heeft vastgezet, verwijst naar een kernel of initrd die niet langer op de schijf staat. Dit gebeurt meestal omdat het pakket is verwijderd terwijl de identifier in grubenv is blijven staan. Herstel vindt plaats door via de console op te starten met een werkend item en vervolgens de verouderde waarde te wissen.

uname -r is ongewijzigd na een herstart waarbij u verandering verwachtte. Controleer in deze volgorde drie zaken: toont grub-editenv list nog steeds uw waarde of is deze verwerkt; verschijnt de identifier die u heeft ingesteld in de huidige grub.cfg; bevat grub.cfg een set default-regel die de variabele leest die u heeft ingesteld. Eén van deze drie verklaart het probleem altijd.

Het menu verscheen uit zichzelf na een crash. GRUB registreert een mislukte boot in grubenv als recordfail=1. Dit dwingt het menu af bij de volgende opstart, zodat een beheerder kan ingrijpen. Wis dit met sudo grub-editenv /boot/grub/grubenv unset recordfail zodra de machine weer gezond is.


De enige zin die u moet onthouden: het bestand dat u bewerkt is niet het bestand dat GRUB leest. Bij een cloud-image bevindt de verwarring zich precies in de kloof tussen deze twee. Lees eerst de gegenereerde configuratie. Elke beslissing op deze pagina vloeit voort uit wat daar daadwerkelijk staat.

FAQ

Waarom wijzigt GRUB_DEFAULT=1 niet welke kernel mijn VPS opstart?

Omdat de gegenereerde /boot/grub/grub.cfg op een Ubuntu cloud-image vaak slechts één boot-entry bevat, waardoor index 1 naar niets verwijst en GRUB terugvalt op het eerste item. Controleer dit met sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg. Een telling van 1 is het resultaat. De oorzaak is GRUB_FORCE_PARTUUID, ingesteld door de image-leverancier in een bestand onder /etc/default/grub.d/, wat de generator op een direct boot-pad plaatst in plaats van een volledige lijst met geïnstalleerde kernels op te bouwen. Zoek het bestand met grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/.

Hoe start ik eenmalig de vorige kernel op?

Voer sudo grub-reboot '<identifier>' uit met een identifier die u kopieert uit uw eigen grub.cfg, en start daarna opnieuw op terwijl de console van de provider al geopend is. GRUB wist next_entry voordat het opstart, dus de keuze geldt voor precies één poging en een kernel die een kernel panic veroorzaakt, wordt niet opnieuw geprobeerd. Controleer of de waarde is opgeslagen met sudo grub-editenv list. Voordat u hierop vertrouwt, voert u sudo grep -n next_entry /boot/grub/grub.cfg uit, omdat een image waarvan de configuratie nooit grubenv laadt, het commando zonder foutmelding zal negeren.

Moet ik vastzetten op basis van het nummer van de entry of op basis van de identifier?

Op basis van de identifier. Entry-nummers zijn posities in een lijst die 10_linux herbouwt met de nieuwste bovenaan, dus het installeren of verwijderen van een kernel verschuift deze nummers. Een verouderde 1>2 verwijst dan nog steeds naar een bestaande, maar onjuiste entry zonder dat u hiervoor een waarschuwing krijgt. Identifiers bevatten de kernelversie, waardoor ze ofwel overeenkomen met de beoogde kernel, ofwel niet worden gevonden. Vermeld ze met sudo grep -n menuentry_id_option /boot/grub/grub.cfg en kopieer de geciteerde string die op elke entry-regel volgt.

Is het vasthouden van het kernel-pakket veiliger dan het wijzigen van de bootloader?

Voor het gebruikelijke doel wel. sudo apt-mark hold linux-image-virtual linux-headers-virtual voorkomt dat er überhaupt een nieuwere kernel wordt geïnstalleerd, waardoor het boot-pad nooit verandert en er niets mis kan gaan vanaf een console die u wellicht niet heeft. Controleer eerst de namen van de geïnstalleerde varianten op uw eigen systeem met apt list --installed en verifieer de 'hold'-status met apt-mark showhold. Het nadeel is dat een vastgehouden kernel geen beveiligingsupdates ontvangt; bepaal dus wanneer u sudo apt-mark unhold uitvoert voordat u de 'hold' instelt.