Corrigindo "sudo: unable to resolve host"

Corrigindo "sudo: unable to resolve host"

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

Conclusao: E um aviso, nao um erro. Significa que o sudo nao conseguiu resolver seu proprio hostname na inicializacao. O comando geralmente ainda e executado, mas cada invocacao espera alguns segundos ate o timeout da consulta. A causa quase sempre se resume a uma divergencia entre hostname e /etc/hosts.

Quando voce executa sudo, uma linha como esta aparece antes da saida 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 nao pode ser resolvido". O ponto-chave e que o sudo geralmente ainda e executado ate o fim mesmo quando voce ve essa mensagem. Nada esta "quebrado" -- o sudo esta simplesmente informando que seu proprio hostname nao esta registrado em nenhum lugar no caminho de resolucao de nomes.

Porem, ha um efeito colateral. O sudo espera o resolver expirar antes de desistir, entao cada invocacao do sudo sofre um atraso de alguns segundos. O aviso em si e inofensivo, mas esse atraso e o que torna a correcao necessaria.

Pre-requisitos

  • SO: Linux tipico, principalmente familia Ubuntu / Debian
  • Permissao para editar /etc/hostname / /etc/hosts (se o sudo ainda funciona, mesmo lento, esta tudo bem)
  • Mais comum logo apos uma mudanca de hostname, ou em imagens de nuvem e containers

Por que o sudo resolve seu proprio hostname?

Conclusao: O sudo precisa saber em qual host esta sendo executado para avaliar regras Host no sudoers e para gravar entradas de log. Portanto, ele resolve seu proprio hostname na inicializacao e emite um aviso quando isso falha.

O sudoers suporta regras Host / Host_Alias que habilitam uma regra apenas em hosts especificos. Para avalia-las, o sudo precisa saber "em qual host estou executando agora". Ele obtem 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 configuracao de servidor unico geralmente nao usa specs Host, mas o sudo tenta a resolucao na inicializacao de qualquer forma. Ele tambem referencia o hostname para registrar "quem executou o que em qual host" no syslog. Portanto, quando o proprio hostname nao pode ser resolvido, o aviso aparece antes do trabalho real.

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

Onde esta a causa?

Conclusao: A causa quase sempre e uma divergencia entre /etc/hostname (o hostname atual) e /etc/hosts (a tabela de nomes estatica). O caso classico: voce mudou o hostname mas nunca atualizou o /etc/hosts.

Resolver o proprio hostname normalmente verifica /etc/hosts primeiro (porque files vem primeiro na linha hosts: do /etc/nsswitch.conf). Se o hostname atual nao tem uma entrada la, a consulta passa para o DNS, falha la tambem e desiste. As causas organizadas:

Causa Quando acontece Por onde comecar
/etc/hosts nao atualizado apos renomear Executou apenas hostnamectl set-hostname cat /etc/hosts
Linha do proprio host ausente em /etc/hosts Imagem de nuvem / cloud-init / edicao manual errada getent hosts NAME
Apenas /etc/hostname foi editado Apos reboot, hostname diverge do hosts hostname
Linha hosts: quebrada no nsswitch.conf files ausente / ordem errada cat /etc/nsswitch.conf

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

Em ambientes de nuvem e containers, o hostname pode ser atribuido dinamicamente a cada boot, ou o cloud-init pode gerenciar o /etc/hosts. Se suas edicoes manuais sao sobrescritas no reboot, bloqueie-o atraves do caminho de gerenciamento na secao "mudanca permanente" abaixo.

Como confirmar?

Conclusao: 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 e a causa direta.

Primeiro, verifique o hostname em uso.

$ hostname
myserver

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

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

Neste exemplo nao ha nenhuma linha para myserver. localhost esta presente, mas o nome do proprio host nao esta registrado. Finalmente, confirme se ele realmente resolve pelo resolver com getent.

$ getent hosts myserver
(sem saida = nao resolve)

Se getent hosts <nome> nao retornar nada, esse nome nao existe em lugar algum no caminho de resolucao. Este e o gatilho direto para sudo: unable to resolve host. Em um host saudavel, ele retorna o IP e o nome.

$ getent hosts web01
127.0.1.1       web01

getent hosts reproduz a resolucao 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?

Conclusao: Basta adicionar uma linha para o hostname atual no /etc/hosts. Na familia Debian/Ubuntu, a convencao e 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), voce pode usa-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

Apos salvar, confirme que ele resolve imediatamente.

$ getent hosts myserver
127.0.1.1       myserver

Se retornar o IP e o hostname, a correcao esta completa. As execucoes subsequentes do sudo nao mostrarao mais o aviso nem o atraso. A configuracao entra em vigor no momento em que voce salva o arquivo -- nao e necessario reiniciar o sistema ou servicos.

Por que 127.0.1.1 e nao 127.0.0.1: A convencao do Debian coloca localhost (127.0.0.1) e o proprio hostname (127.0.1.1) em linhas separadas para hosts com FQDN. Coloca-los na mesma linha pode fazer com que alguns softwares tratem "nome do host = localhost" e se comportem mal. Se voce tem um IP estatico atribuido, pode usar esse IP real, mas 127.0.1.1 e a escolha segura em DHCP.

Para adicionar em uma linha, faca o seguinte. Para evitar uma entrada duplicada, verifique a existencia com grep antes.

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

Como alterar o hostname permanentemente?

Conclusao: Ao alterar o hostname, sempre atualize hostnamectl set-hostname e /etc/hosts juntos. Fazer apenas um deles e exatamente como voce cria esse aviso.

Se voce quer alterar o hostname em si (e essa mudanca causou o aviso), use o hostnamectl do systemd. Ele reescreve /etc/hostname e aplica a mudanca ao sistema em execucao 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 nao atualiza /etc/hosts automaticamente. Portanto, apos a mudanca, 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 voce defina preserve_hostname: true em /etc/cloud/cloud.cfg. Se suas edicoes manuais desaparecem, suspeite desse caminho de gerenciamento.

Logo apos uma mudanca, tentar o sudo pode confundi-lo com credenciais em cache obsoletas no shell. Execute sudo -k para limpar o cache de autenticacao antes de tentar novamente, assim voce pode isolar se e puramente um problema de resolucao de nomes.

Checklist quando ainda falha

Conclusao: 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 digitacao e espacos em branco sao as armadilhas classicas.

  • [ ] A saida de hostname e a entrada em /etc/hosts coincidem caractere por caractere?
  • [ ] Voce 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 comeca com files (hosts: files dns)?
  • [ ] Para um FQDN, voce listou ambas as formas, ex: 127.0.1.1 web01.example.com web01?
  • [ ] Se reverte apos reboot em nuvem/container, voce verificou o preserve_hostname do cloud-init?
  • [ ] Apos editar, voce limpou o cache de autenticacao com sudo -k e verificou novamente?

Proximas leituras