SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-25

Como fixar o kernel que o VPS inicia no próximo boot

Em imagens cloud Ubuntu, GRUB_DEFAULT pode não funcionar. Veja as entradas reais do GRUB, entenda a origem do menu e fixe o próximo kernel sem perder o acesso SSH.

O que decide qual kernel o seu VPS arranca

Qual kernel o seu VPS arranca da próxima vez é decidido por um único ficheiro gerado, /boot/grub/grub.cfg. Nunca edite esse ficheiro. Edite as entradas que lhe dão origem e volte a gerá-lo. Numa imagem cloud Ubuntu, uma dessas entradas vem do fornecedor da imagem e pode tornar irrelevante a seleção do menu. É por isso que GRUB_DEFAULT=1 seguido de update-grub não altera nada num servidor alugado, embora os mesmos dois passos funcionem numa instalação num portátil.

Siga esta ordem. Confirme que pode escolher o kernel. Leia todos os ficheiros de entrada, incluindo os adicionados pelo fornecedor. Leia a saída gerada e conte as entradas que ela contém realmente. Só depois escolha um método de fixação. Se fizer isto de forma incorreta numa máquina à qual só acede por SSH, poderá precisar de uma consola de recuperação. Por isso, as opções mais seguras estão no fim desta página e são frequentemente as corretas.

Primeiro, confirme se pode definir o kernel como padrão

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

systemd-detect-virt a imprimir kvm, qemu ou xen significa que está a executar o seu próprio kernel e que tudo o que se segue se aplica. lxc ou openvz significa que o servidor partilha o kernel do host. Nesse caso, não existe um bootloader seu nem um kernel que possa definir como padrão. Nesse caso, uname -r apresenta uma versão que nem sequer aparece em /boot/vmlinuz-*, porque o kernel em execução pertence ao host e nenhuma configuração no seu disco pode alterá-lo.

ls -1 /boot/vmlinuz-* é a lista real dos kernels que pode escolher. Se tiver uma única linha, o kernel anterior já foi eliminado e nenhuma configuração do bootloader o pode recuperar. Isto costuma acontecer durante um autoremove. Vale a pena compreender esse processo antes de limpar kernels antigos no Ubuntu num servidor importante.

O ficheiro que edita não é o ficheiro que o GRUB lê

/etc/default/grub contém atribuições simples de variáveis da shell. É uma entrada. /boot/grub/grub.cfg é a saída e começa com # DO NOT EDIT THIS FILE e o motivo. Tudo o que escrever na saída desaparece na próxima vez que um pacote do kernel for instalado ou removido, porque esses scripts dos pacotes geram o ficheiro novamente.

cat /usr/sbin/update-grub

update-grub é um wrapper. Executa grub-mkconfig -o /boot/grub/grub.cfg, que lê as variáveis, executa todos os scripts em /etc/grub.d/ e escreve o resultado. São dois comandos numa só direção: as entradas são fornecidas, e grub.cfg é gerado.

O que substitui a sua configuração: /etc/default/grub.d

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

O segundo caminho é a parte que costuma passar despercebida. grub-mkconfig carrega primeiro /etc/default/grub e, depois, todos os ficheiros *.cfg em /etc/default/grub.d/ pela ordem dos padrões glob. Leia o código que faz isso:

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

O carregamento é feito por uma shell normal, por isso a última atribuição prevalece. As imagens cloud do Ubuntu incluem ficheiros nesse diretório e definem valores como o tempo limite e a linha de comandos do kernel depois de o seu ficheiro já ter sido lido. O seu GRUB_TIMEOUT=10 em /etc/default/grub é substituído instantes depois por um ficheiro do fornecedor que o define como 0. O grep acima mostra as atribuições exatas na sua imagem, por isso consulte esses valores em vez de confiar nesta frase.

A regra prática é colocar as suas próprias configurações num ficheiro que fique por último na ordenação, como /etc/default/grub.d/99-local.cfg, em vez de editar /etc/default/grub. Assim, nada fornecido pela imagem será carregado depois do seu ficheiro.

Por que GRUB_FORCE_PARTUUID torna irrelevante a seleção no menu

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 instrui o gerador a localizar o sistema de ficheiros raiz pelo UUID da partição, escrito diretamente na linha de comandos do kernel como root=PARTUUID=..., em vez de procurar um UUID de sistema de ficheiros durante o arranque. O fornecedor da imagem define esta variável porque isso permite que uma única imagem de disco arranque de forma fiável em hardware diferente daquele onde foi criada. O segundo grep mostra o código que atua sobre a variável, em /etc/grub.d/10_linux. Esse script está no seu próprio disco e é a autoridade sobre o comportamento da sua imagem.

A consequência é o que importa aqui: nesse caminho, o gerador escreve uma entrada de arranque direta, em vez de uma lista completa dos kernels instalados. Conte quantas entradas foram criadas.

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

Se a contagem for 1, não existe uma segunda entrada para selecionar. Portanto, GRUB_DEFAULT=1 indica uma entrada que não existe. O GRUB não consegue resolvê-la e arranca a primeira entrada, que é o novo kernel que estava a tentar evitar. grub-set-default também não ajuda, porque o problema não está no valor predefinido. O menu que está a tentar selecionar nunca foi gerado.

Para restaurar um menu completo, mova o ficheiro do fornecedor para outro nome e faça uma pré-visualização do resultado antes de o aplicar. grub-mkconfig sem -o escreve na saída padrão e não altera nada no disco.

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

Uma contagem que passa de 1 para várias entradas significa que as entradas aparecem quando a imposição é removida. Nada foi escrito ainda. Restaure o ficheiro se a segunda contagem não parecer correta, porque o PARTUUID imposto é o mecanismo usado pela imagem do seu fornecedor para localizar o sistema de ficheiros raiz, e removê-lo transfere a máquina para o caminho de pesquisa. Crie um snapshot antes de executar update-grub efetivamente.

Se o seu único objetivo for ultrapassar um kernel problemático, pare aqui e use as opções mais seguras apresentadas abaixo. Reconstruir o menu de arranque num servidor remoto para contornar uma única atualização envolve mais risco do que o problema justifica.

Por que fixar números de entrada é uma má prática

GRUB_DEFAULT aceita um número, um título ou um identificador. Os números contam as entradas de nível superior a partir de 0. Uma entrada aninhada usa > como separador. Assim, GRUB_DEFAULT="1>2" significa a entrada no índice 2 dentro do submenu no índice 1.

Os índices mudam. 10_linux lista os kernels do mais recente para o mais antigo. Por isso, instalar um kernel desloca cada entrada mais antiga uma posição para baixo, e remover um kernel desloca-as para cima. O seu 1>2 cuidadosamente definido continua a ser resolvido depois dessa alteração. Agora, identifica um kernel diferente. Não ocorre nenhum erro nem é apresentada qualquer advertência. Só descobre o problema depois de um reboot.

Os identificadores não mudam, porque cada um contém a versão do kernel. Leia os seus identificadores:

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

Ignore as primeiras linhas da saída. Elas mostram a variável que está a ser definida no cabeçalho. Depois disso, o lado esquerdo é o título apresentado ao utilizador e o lado direito é o identificador que deve passar às ferramentas. Para uma entrada dentro de um submenu, junte o identificador do submenu ao identificador da entrada com >, exatamente nessa ordem, tal como na forma numérica.

Arranque uma vez o kernel anterior com grub-reboot

Uma seleção única é a opção correta num servidor remoto porque é automaticamente revertida. grub-reboot grava next_entry em /boot/grub/grubenv. O GRUB lê essa variável, limpa-a e grava o valor limpo antes de arrancar qualquer coisa. Assim, um kernel que entre em panic não é tentado novamente no arranque seguinte. É feita uma única tentativa. Depois, a máquina regressa automaticamente ao seu padrão normal.

Confirme primeiro se a configuração gerada lê essa variável:

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

Deve encontrar uma linha load_env e um bloco que define default a partir de next_entry. Se o grep não produzir qualquer saída, a sua imagem nunca lê grubenv durante o arranque. Nesse caso, grub-reboot será aceite pela shell e depois ignorado pelo bootloader. É o mesmo caminho de arranque direto forçado da secção anterior, agora apresentado num segundo local.

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

grub-editenv list deve agora apresentar uma linha next_entry= com exatamente o valor fornecido. Abra a consola do seu fornecedor num separador do browser. Depois, reinicie e verifique o resultado.

sudo reboot
uname -r

Se uname -r apresentar a versão anterior, o bloqueio funcionou. Se apresentar a versão nova, o identificador não foi resolvido ou grubenv não está a ser lido. Em qualquer dos casos, a máquina está operacional. Esse é o objetivo de utilizar a forma de execução única.

Faça a escolha persistir com GRUB_DEFAULT=saved

GRUB_DEFAULT=saved faz com que o valor predefinido venha de saved_entry em grubenv, e esse valor é definido com grub-set-default. A configuração sobrevive às instalações de kernels, porque update-grub reescreve grub.cfg e nunca altera grubenv.

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

O último comando deve imprimir set default="${saved_entry}". Se imprimir set default="0", algo carregado depois do seu ficheiro definiu GRUB_DEFAULT novamente com um valor literal. Nesse caso, liste /etc/default/grub.d/ outra vez e confirme que 99-local.cfg fica realmente em último lugar na ordenação.

GRUB_SAVEDEFAULT=true é uma definição diferente e é fácil confundi-la com esta. Ela guarda o kernel que acabou de arrancar como o novo valor predefinido. Assim, o valor predefinido passa a seguir o último arranque bem-sucedido. Num servidor, isso significa que um reboot não supervisionado pode alterar silenciosamente a sua escolha fixa. Deixe esta opção desativada, a menos que seja esse o comportamento pretendido.

Uma escolha fixa por identificador ainda pode falhar de uma forma. Se remover o kernel identificado, o identificador deixa de ser resolvido e o sistema volta à primeira entrada. Por isso, mantenha também o pacote instalado ou impeça que esse kernel seja removido automaticamente.

Colocar o menu na consola do provedor

A seleção interativa exige que o menu seja apresentado no ecrã, mas as imagens cloud ocultam-no. Coloque estas linhas no ficheiro que é processado por último e execute sudo update-grub.

GRUB_TIMEOUT=10
GRUB_TIMEOUT_STYLE=menu
GRUB_RECORDFAIL_TIMEOUT=10

GRUB_TIMEOUT_STYLE=hidden em conjunto com GRUB_TIMEOUT=0 não apresenta nada, por isso quem observa a consola vê imediatamente o início das mensagens do kernel e conclui que o bootloader foi ignorado. GRUB_RECORDFAIL_TIMEOUT é o timeout separado usado depois de um boot que não foi concluído. As imagens cloud também o definem como 0. Por isso, um servidor que acabou de falhar durante o boot continua sem parar e aguardar a sua intervenção.

Se o provedor disponibilizar uma consola série em vez de uma consola gráfica e continuar sem ver nada, o GRUB está a escrever num terminal que não consegue ver. Adicione as duas linhas em conjunto, porque a primeira seleciona as saídas e a segunda configura a porta:

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

A partir de agora, são adicionados dez segundos a cada boot. Defina novamente o timeout como 0 quando terminar.

Opções mais seguras do que editar o bootloader

Alterar a entrada do bootloader numa máquina à qual só acede por SSH é a opção de maior risco desta página. Existem alternativas mais simples, que normalmente resolvem o problema real.

Impeça a atualização dos pacotes do kernel. Se o objetivo é "não me entregue um kernel mais recente", indique isso ao gestor de pacotes, não ao 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

Use os nomes apresentados pelo primeiro comando, porque as imagens cloud instalam frequentemente a variante virtual ou kvm, em vez de generic. Se o kernel mais recente apareceu durante uma atualização da imagem e suspeita que a própria release mudou, isso não aconteceu, porque uma point release contém as atualizações que já foram incorporadas num novo meio de instalação e não entrega a um servidor já corrigido nada que não lhe tivesse sido disponibilizado semanas antes. Um pacote mantido é ignorado pelo apt upgrade, que o indica com The following packages have been kept back:, e também é ignorado pelas atualizações automáticas no Ubuntu. O custo é real: um kernel mantido deixa de receber correções de segurança. Trate esta medida como uma pausa com uma data definida e liberte o pacote com sudo apt-mark unhold. Se evita atualizações do kernel porque os reboots causam indisponibilidade, e não porque um kernel específico apresenta problemas, a aplicação de patches ao kernel em tempo real numa VPS resolve esse problema.

Crie um snapshot antes da atualização. Um snapshot pode ser restaurado em minutos, sem introduzir comandos na consola e sem risco de aplicar apenas parte de uma alteração ao bootloader. Crie o snapshot, atualize, faça reboot e verifique. Se o novo kernel apresentar problemas, reverta para o snapshot. O caminho de boot ficará exatamente como estava.

Use a consola ou uma imagem de recuperação numa máquina que já esteja indisponível. Quando o servidor deixa de arrancar, a configuração do bootloader não é o local onde deve corrigir o problema. Esse processo de recuperação é independente: o que fazer quando uma VPS não arranca depois de uma atualização do kernel.

O que falha e a mensagem apresentada

A sua alteração em /boot/grub/grub.cfg desapareceu. Um pacote do kernel foi instalado ou removido, o script do maintainer foi executado em update-grub e o ficheiro foi gerado novamente a partir das entradas. O cabeçalho # DO NOT EDIT THIS FILE identifica as duas localizações de entrada. Edite essas localizações.

grub-editenv: error: environment block too small. /boot/grub/grubenv está em falta ou truncado. Recrie-o com sudo grub-editenv /boot/grub/grubenv create, defina novamente o seu valor e confirme com sudo grub-editenv list.

Um kernel fixado entra em panic com VFS: Unable to mount root fs on unknown-block(0,0). A entrada fixada aponta para um kernel ou initrd que já não está no disco, normalmente porque o pacote foi removido enquanto o identificador permaneceu em grubenv. A recuperação consiste em arrancar pela consola usando uma entrada funcional e, em seguida, limpar o valor obsoleto.

uname -r não mudou depois de um reboot que deveria alterá-lo. Verifique três coisas, pela ordem: grub-editenv list ainda mostra o seu valor ou esse valor já foi consumido; o identificador que definiu aparece no grub.cfg atual; grub.cfg contém uma linha set default que lê a variável definida. Uma dessas três condições explica sempre o problema.

O menu apareceu sozinho depois de um crash. O GRUB regista um boot falhado em grubenv como recordfail=1. Isso força a apresentação do menu no boot seguinte para permitir a intervenção humana. Limpe-o com sudo grub-editenv /boot/grub/grubenv unset recordfail quando a máquina estiver estável.


A frase que vale a pena guardar é esta: o ficheiro que edita não é o ficheiro que o GRUB lê e, numa imagem cloud, a diferença entre os dois é a origem da confusão. Leia primeiro a configuração gerada. Todas as decisões desta página resultam do conteúdo efetivo dessa configuração.

FAQ

Por que GRUB_DEFAULT=1 não altera o kernel com que a minha VPS arranca?

Porque, numa imagem cloud do Ubuntu, o /boot/grub/grub.cfg gerado contém frequentemente uma única entrada de arranque. Assim, o índice 1 não identifica nada e o GRUB recorre à primeira entrada. Confirme com sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg. Um total de 1 é a resposta. A causa é GRUB_FORCE_PARTUUID, definido pelo fornecedor da imagem num ficheiro em /etc/default/grub.d/. Esta configuração faz o gerador seguir um caminho de arranque direto, em vez de criar uma lista completa dos kernels instalados. Encontre o ficheiro com grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/.

Como arranco o kernel anterior apenas uma vez?

Execute sudo grub-reboot '<identifier>' com um identificador copiado do seu próprio grub.cfg. Em seguida, reinicie com a consola do fornecedor já aberta. O GRUB limpa next_entry antes de arrancar. Assim, a escolha aplica-se exatamente a uma tentativa e um kernel que entre em panic não é tentado novamente. Confirme que o valor foi aplicado com sudo grub-editenv list. Antes de depender deste método, execute sudo grep -n next_entry /boot/grub/grub.cfg, porque uma imagem cuja configuração nunca carrega grubenv ignora o comando sem apresentar qualquer erro.

Devo fixar o kernel pelo número da entrada ou pelo identificador?

Pelo identificador. Os números das entradas são posições numa lista que 10_linux recria começando pelo kernel mais recente. Por isso, instalar ou remover qualquer kernel altera essas posições. Um 1>2 desatualizado continua a resolver para uma entrada real, mas incorreta, sem apresentar qualquer aviso. Os identificadores contêm a versão do kernel. Assim, correspondem ao kernel pretendido ou não resolvem. Liste-os com sudo grep -n menuentry_id_option /boot/grub/grub.cfg e copie a cadeia entre aspas que aparece a seguir em cada linha de entrada.

Manter o pacote do kernel é mais seguro do que alterar o bootloader?

Para o objetivo habitual, sim. sudo apt-mark hold linux-image-virtual linux-headers-virtual impede totalmente a instalação de um kernel mais recente. Assim, o caminho de arranque nunca muda e não há nada que possa ser configurado incorretamente a partir de uma consola à qual talvez não tenha acesso. Primeiro, confirme os nomes das variantes instaladas no seu próprio servidor com apt list --installed e verifique o bloqueio com apt-mark showhold. A desvantagem é que um kernel bloqueado não recebe correções de segurança. Por isso, decida quando vai executar sudo apt-mark unhold antes de aplicar o bloqueio.