Corrigindo Avisos "cannot set LC_ALL" de Locale
O Que Você Vai Aprender
- Por que o aviso
cannot set LC_ALL/setlocaleaparece - Como identificar a variável ofensora com
locale/locale -a - Como silenciar rapidamente e como gerar o locale para uma correção permanente
Conclusão (padrão de triagem)
- O aviso significa uma coisa: o locale solicitado não existe no sistema
- Primeiro verifique o aviso com
locale, depois os locales que você realmente tem comlocale -a - Se estiver ausente, gere com
locale-gen; se tiver pressa, silencie comexport LC_ALL=C
Premissas (ambiente alvo)
- SO: Ubuntu / Debian / família RHEL (glibc com systemd)
- Pode acontecer em terminal local, servidor SSH alvo ou container
Por que o aviso "cannot set LC_ALL" aparece?
Conclusão: Porque o locale que suas variáveis
LANG/LC_*solicitam (ex:en_US.UTF-8) não está gerado ou instalado naquele sistema. Ao solicitar um locale que não existe, a glibc faz fallback para o locale C.
Um locale agrupa idioma, codificação de caracteres e formatação de data/número sob um nome como en_US.UTF-8 ou ja_JP.UTF-8. Na inicialização, um programa chama setlocale() e resolve o locale solicitado na ordem de prioridade: LC_ALL → LC_* → LANG.
Quando o nome solicitado não existe no sistema, a glibc emite um aviso e faz fallback para o locale seguro C (POSIX). Mensagens típicas:
# o proprio comando locale
locale: Cannot set LC_ALL to default locale: No such file or directory
# bash / varios comandos
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory
# perl (comum em apt e hooks do Git)
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = (unset),
LC_CTYPE = "UTF-8",
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
Principais padrões de "não existe"
- O pacote
localesem si não está instalado (containers mínimos, imagens cloud) - O pacote está presente mas o locale nunca foi gerado (
locale-gennão executado) - O SSH encaminhou o locale do seu terminal e o servidor alvo não tem o mesmo
- Um erro de digitação (ex: omitir o codeset como em
en_USem vez deen_US.UTF-8, ou separador errado comoen-US.UTF-8) aponta para um nome que não existe
Como encontro qual variável está errada?
Conclusão: Use
localepara os valores atuais e a variável ofensora, elocale -apara a lista de locales disponíveis. Se o nome solicitado não está na lista, essa é a causa.
Executar locale mostra as configurações atuais e qual variável é o problema de uma vez.
$ locale
locale: Cannot set LC_ALL to default locale: No such file or directory LANG=en_US.UTF-8 LANGUAGE= LC_CTYPE="en_US.UTF-8" LC_NUMERIC="en_US.UTF-8" ... LC_ALL=
Em seguida, liste os locales que o sistema pode realmente usar.
$ locale -a
C C.UTF-8 POSIX
Aqui en_US.UTF-8 é solicitado, mas a lista tem apenas locales da família C. O nome solicitado não aparecer em locale -a é a evidência decisiva.
Atenção para variações de nome. locale -a pode imprimir na forma en_US.utf8 (minúsculo, sem hífen), mas uma configuração LANG=en_US.UTF-8 é tratada como a mesma. Entretanto, en_US (sem codificação) e en_US.UTF-8 são diferentes, então verifique se o sufixo também corresponde.
Por que o aviso aparece via SSH?
Conclusão: O cliente SSH encaminha seu locale local com
SendEnv LANG LC_*, e o servidor aceita viaAcceptEnv. Se o servidor não tem aquele locale, você recebe o aviso em cada login.
Se nunca aparece localmente mas aparece toda vez que você se conecta via SSH a um servidor, esta é quase sempre a causa. A maioria das distros vem com uma configuração de cliente SSH com esta linha:
# /etc/ssh/ssh_config ou ~/.ssh/config SendEnv LANG LC_*
Isso envia seu LANG=en_US.UTF-8 (e similares) para o servidor. O AcceptEnv LANG LC_* do /etc/ssh/sshd_config do servidor os recebe e configura o ambiente da sessão. Se o servidor não tem aquele locale, setlocale falha quando o shell inicia.
Você tem duas opções: instalar o locale no servidor (passos abaixo) ou parar de encaminhá-lo. Para parar o encaminhamento, edite a configuração do cliente.
# Desabilitar encaminhamento para um host em ~/.ssh/config
Host myserver
SendEnv -LANG -LC_*Para evitar o aviso de locale em uma única conexão, envie o locale C que está sempre presente para sobrescrevê-lo. LC_ALL tem precedência sobre todos os outros LC_* e LANG, então ele vence mesmo quando um valor foi encaminhado.
$ LC_ALL=C ssh user@myserver
Como gerar ou instalar o locale? (Debian / Ubuntu)
Conclusão: Instale o pacote
locales, gere o locale alvo comlocale-gene defina o padrão comupdate-locale. O interativodpkg-reconfigure localesfaz o mesmo.
No Debian / Ubuntu, um locale requer dois passos: instalar o pacote e gerá-lo.
# 1. O pacote locales (para sistemas minimos sem ele) $ sudo apt update && sudo apt install -y locales # 2. Gerar os locales alvo $ sudo locale-gen en_US.UTF-8 ja_JP.UTF-8 # 3. Definir o locale padrao do sistema $ sudo update-locale LANG=en_US.UTF-8
Verifique novamente com locale -a que foi gerado. A configuração persistente fica em /etc/default/locale.
$ cat /etc/default/locale
LANG=en_US.UTF-8
Para escolher de um menu, use o comando abaixo e selecione locales com a barra de espaço para gerá-los.
$ sudo dpkg-reconfigure locales
Mudanças de update-locale e /etc/default/locale só entram em vigor a partir de uma nova sessão de login. Para aplicá-las ao shell atual imediatamente, faça logout e login novamente, ou defina um valor por enquanto com export LANG=en_US.UTF-8.
Corrigindo no RHEL / Fedora
Conclusão: No RHEL 8 e posterior, instale o locale via pacote
glibc-langpack-<lang>e defina o padrão comlocalectl set-locale.
No RHEL / CentOS Stream / Fedora, você instala um langpack por idioma.
# O conjunto de locale ingles $ sudo dnf install -y glibc-langpack-en # Adicione japones se precisar $ sudo dnf install -y glibc-langpack-ja # Definir o padrao do sistema $ sudo localectl set-locale LANG=en_US.UTF-8
localectl é o comando comum de gerenciamento de locale em sistemas systemd, e ele escreve a configuração em /etc/locale.conf. Verifique o valor atual com localectl status.
$ localectl status
System Locale: LANG=en_US.UTF-8
VC Keymap: us
X11 Layout: us
Em um sistema da família Debian que também tem localectl (systemd), você pode definir o padrão com localectl set-locale também. Mas gerar o locale continua sendo trabalho do locale-gen, então a ordem gerar → localectl permanece a mesma.
Um workaround rápido quando você só quer silenciar
Conclusão: Use
export LC_ALL=Couexport LANG=C.UTF-8para mudar para um locale que certamente existe. Não é uma correção real, mas para o aviso instantaneamente.
Para uma execução de script ou tarefa pontual onde você "só quer que o aviso pare agora", aponte para um locale da família C que certamente existe.
# Silenciar completamente (mensagens em ingles, collation ASCII) $ export LC_ALL=C # Manter UTF-8 (disponivel na maioria dos sistemas) $ export LANG=C.UTF-8 $ unset LC_ALL
C (= POSIX) e C.UTF-8 são embutidos na glibc e funcionam em quase todo lugar sem locale-gen. Escolher C.UTF-8 mantém sequências de bytes UTF-8 intactas enquanto usa mensagens em inglês.
LC_ALL é a variável de maior prioridade que sobrescreve todo LC_*. Fixá-la em C força a classificação de caracteres e ordem de ordenação para o locale C também. Colocar LC_ALL=C em um arquivo permanente (como .bashrc) convida outros bugs, então mantenha como workaround e corrija permanentemente gerando o locale.
Se você só quer silenciar um único script, delimite no topo.
#!/usr/bin/env bash export LC_ALL=C.UTF-8
Checklist para prevenir recorrência
Conclusão: Pré-gere os locales que um servidor precisa, pare forwarding SSH desnecessário e evite fixar
LC_ALLpermanentemente, e avisos de locale são amplamente preveníveis.
| Medida | Comando / configuração | Efeito |
|---|---|---|
| Gerar locales necessários | sudo locale-gen en_US.UTF-8 |
Remove o nome solicitado ausente |
| Definir padrão explícito do sistema | update-locale / localectl set-locale |
Fixa o padrão por login |
| Parar forwarding SSH desnecessário | SendEnv -LANG -LC_* |
Previne importação de locales ausentes |
| Manter workarounds locais | export LC_ALL=C.UTF-8 dentro de script |
Evita efeitos colaterais de fixação global |
Copie e cole: diagnóstico de locale em uma linha
# Compare o locale solicitado contra o que esta disponivel echo "--- solicitado ---"; locale 2>&1 | grep -E '^(LANG|LC_ALL|LC_CTYPE)='; \ echo "--- disponivel ---"; locale -a