Corrigindo "sudo: unable to resolve host"

Corrigindo "sudo: unable to resolve host"

O que significa "sudo: unable to resolve host"?

Conclusão: É um aviso, não um erro. Significa que o sudo não conseguiu resolver seu próprio hostname na inicialização. O comando geralmente ainda é executado, mas cada invocação espera alguns segundos até o timeout da consulta. A causa quase sempre se resume a uma divergência entre hostname e /etc/hosts.

Quando você executa sudo, uma linha como esta aparece antes da saída do comando.

$ sudo apt update
sudo: unable to resolve host myserver: Name or service not known
[sudo] password for user:

A mensagem significa "o hostname myserver não pode ser resolvido". O ponto-chave é que o sudo geralmente ainda é executado até o fim mesmo quando você vê essa mensagem. Nada está "quebrado" -- o sudo está simplesmente informando que seu próprio hostname não está registrado em nenhum lugar no caminho de resolução de nomes.

Porém, há um efeito colateral. O sudo espera o resolver expirar antes de desistir, então cada invocação do sudo sofre um atraso de alguns segundos. O aviso em si é inofensivo, mas esse atraso é o que torna a correção necessária.

Pré-requisitos

  • SO: Linux típico, principalmente família Ubuntu / Debian
  • Permissão para editar /etc/hostname / /etc/hosts (se o sudo ainda funciona, mesmo lento, está tudo bem)
  • Mais comum logo após uma mudança de hostname, ou em imagens de nuvem e containers

Por que o sudo resolve seu próprio hostname?

Conclusão: O sudo precisa saber em qual host está sendo executado para avaliar regras Host no sudoers e para gravar entradas de log. Portanto, ele resolve seu próprio hostname na inicialização e emite um aviso quando isso falha.

O sudoers suporta regras Host / Host_Alias que habilitam uma regra apenas em hosts específicos. Para avaliá-las, o sudo precisa saber "em qual host estou executando agora". Ele obtém o nome de gethostname(2) e o resolve pelo resolver para identificar o host.

# Exemplo de specs Host no sudoers (usado em NIS / gerenciamento central)
user  ALL=(ALL)  ALL          # todos os hosts
user  web01=(ALL)  ALL        # somente no web01

Uma configuração de servidor único geralmente não usa specs Host, mas o sudo tenta a resolução na inicialização de qualquer forma. Ele também referencia o hostname para registrar "quem executou o que em qual host" no syslog. Portanto, quando o próprio hostname não pode ser resolvido, o aviso aparece antes do trabalho real.

Este aviso é um efeito colateral de design do sudo e não tem nada a ver com rede ou acesso à Internet. Mesmo em uma máquina offline, o aviso desaparece desde que o hostname seja resolvido via /etc/hosts.

Onde está a causa?

Conclusão: A causa quase sempre é uma divergência entre /etc/hostname (o hostname atual) e /etc/hosts (a tabela de nomes estática). O caso clássico: você mudou o hostname mas nunca atualizou o /etc/hosts.

Resolver o próprio hostname normalmente verifica /etc/hosts primeiro (porque files vem primeiro na linha hosts: do /etc/nsswitch.conf). Se o hostname atual não tem uma entrada lá, a consulta passa para o DNS, falha lá também e desiste. As causas organizadas:

Causa Quando acontece Por onde começar
/etc/hosts não atualizado após renomear Executou apenas hostnamectl set-hostname cat /etc/hosts
Linha do próprio host ausente em /etc/hosts Imagem de nuvem / cloud-init / edição manual errada getent hosts NAME
Apenas /etc/hostname foi editado Após reboot, hostname diverge do hosts hostname
Linha hosts: quebrada no nsswitch.conf files ausente / ordem errada cat /etc/nsswitch.conf

A triagem é simples: basta verificar se "o hostname atual" e "o nome escrito no /etc/hosts" coincidem. Se não coincidirem, essa é a causa.

Em ambientes de nuvem e containers, o hostname pode ser atribuído dinamicamente a cada boot, ou o cloud-init pode gerenciar o /etc/hosts. Se suas edições manuais são sobrescritas no reboot, bloqueie-o através do caminho de gerenciamento na seção "mudança permanente" abaixo.

Como confirmar?

Conclusão: Compare o nome atual de hostname com os nomes em cat /etc/hosts, depois confirme com getent hosts <nome> se ele realmente resolve. Se getent retornar vazio, essa é a causa direta.

Primeiro, verifique o hostname em uso.

$ hostname
myserver

Em seguida, olhe dentro do /etc/hosts. Se o nome acima aparece aqui é o ponto crucial.

$ cat /etc/hosts
127.0.0.1   localhost
::1         localhost ip6-localhost ip6-loopback

Neste exemplo não há nenhuma linha para myserver. localhost está presente, mas o nome do próprio host não está registrado. Finalmente, confirme se ele realmente resolve pelo resolver com getent.

$ getent hosts myserver
(sem saida = nao resolve)

Se getent hosts <nome> não retornar nada, esse nome não existe em lugar algum no caminho de resolução. Este é o gatilho direto para sudo: unable to resolve host. Em um host saudável, ele retorna o IP e o nome.

$ getent hosts web01
127.0.1.1       web01

getent hosts reproduz a resolução seguindo a linha hosts: em /etc/nsswitch.conf -- files (= /etc/hosts) depois DNS. Ele percorre quase o mesmo caminho que o sudo usa internamente, o que o torna ideal para triagem.

Como corrigir?

Conclusão: Basta adicionar uma linha para o hostname atual no /etc/hosts. Na família Debian/Ubuntu, a convenção é adicionar 127.0.1.1 <hostname> como uma linha separada de 127.0.0.1 localhost.

Registre o nome de hostname no /etc/hosts. Se o sudo ainda funciona (mesmo com o atraso), você pode usá-lo para editar.

# Obter o hostname atual
$ hostname
myserver

# Editar /etc/hosts (com qualquer editor)
$ sudo nano /etc/hosts

O /etc/hosts editado deve ficar assim. Note a linha 127.0.1.1 adicionada.

127.0.0.1   localhost
127.0.1.1   myserver
::1         localhost ip6-localhost ip6-loopback

Após salvar, confirme que ele resolve imediatamente.

$ getent hosts myserver
127.0.1.1       myserver

Se retornar o IP e o hostname, a correção está completa. As execuções subsequentes do sudo não mostrarão mais o aviso nem o atraso. A configuração entra em vigor no momento em que você salva o arquivo -- não é necessário reiniciar o sistema ou serviços.

Por que 127.0.1.1 e não 127.0.0.1: A convenção do Debian coloca localhost (127.0.0.1) e o próprio hostname (127.0.1.1) em linhas separadas para hosts com FQDN. Colocá-los na mesma linha pode fazer com que alguns softwares tratem "nome do host = localhost" e se comportem mal. Se você tem um IP estático atribuído, pode usar esse IP real, mas 127.0.1.1 é a escolha segura em DHCP.

Para adicionar em uma linha, faça o seguinte. Para evitar uma entrada duplicada, verifique a existência com grep antes.

$ grep -q "$(hostname)" /etc/hosts || echo "127.0.1.1   $(hostname)" | sudo tee -a /etc/hosts

Como alterar o hostname permanentemente?

Conclusão: Ao alterar o hostname, sempre atualize hostnamectl set-hostname e /etc/hosts juntos. Fazer apenas um deles é exatamente como você cria esse aviso.

Se você quer alterar o hostname em si (e essa mudança causou o aviso), use o hostnamectl do systemd. Ele reescreve /etc/hostname e aplica a mudança ao sistema em execução imediatamente.

# Alterar para o novo hostname
$ sudo hostnamectl set-hostname web01

# Confirmar a mudanca
$ hostnamectl status
   Static hostname: web01
         Icon name: computer-vm
            ...

O hostnamectl atualiza /etc/hostname mas não atualiza /etc/hosts automaticamente. Portanto, após a mudança, corrija o hostname antigo no /etc/hosts para o novo.

127.0.0.1   localhost
127.0.1.1   web01
::1         localhost ip6-localhost ip6-loopback

Finalmente, confirme que o novo nome resolve.

$ getent hosts "$(hostname)"
127.0.1.1       web01

Em ambientes com cloud-init, o hostname pode reverter no reboot a menos que você defina preserve_hostname: true em /etc/cloud/cloud.cfg. Se suas edições manuais desaparecem, suspeite desse caminho de gerenciamento.

Logo após uma mudança, tentar o sudo pode confundi-lo com credenciais em cache obsoletas no shell. Execute sudo -k para limpar o cache de autenticação antes de tentar novamente, assim você pode isolar se é puramente um problema de resolução de nomes.

Checklist quando ainda falha

Conclusão: Se o aviso persistir, verifique em ordem se hostname e /etc/hosts coincidem exatamente, e se a linha hosts: no nsswitch.conf tem files. Erros de digitação e espaços em branco são as armadilhas clássicas.

  • [ ] A saída de hostname e a entrada em /etc/hosts coincidem caractere por caractere?
  • [ ] Você adicionou a linha 127.0.1.1 <hostname> (ou IP real) ao /etc/hosts?
  • [ ] O getent hosts "$(hostname)" agora retorna um IP?
  • [ ] A linha hosts: no /etc/nsswitch.conf começa com files (hosts: files dns)?
  • [ ] Para um FQDN, você listou ambas as formas, ex: 127.0.1.1 web01.example.com web01?
  • [ ] Se reverte após reboot em nuvem/container, você verificou o preserve_hostname do cloud-init?
  • [ ] Após editar, você limpou o cache de autenticação com sudo -k e verificou novamente?

Próximas leituras