Corrigindo Avisos "cannot set LC_ALL" de Locale
O Que Voce Vai Aprender
- Por que o aviso
cannot set LC_ALL/setlocaleaparece - Como identificar a variavel ofensora com
locale/locale -a - Como silenciar rapidamente e como gerar o locale para uma correcao permanente
Conclusao (padrao de triagem)
- O aviso significa uma coisa: o locale solicitado nao existe no sistema
- Primeiro verifique o aviso com
locale, depois os locales que voce 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 / familia RHEL (glibc com systemd)
- Pode acontecer em terminal local, servidor SSH alvo ou container
Por que o aviso "cannot set LC_ALL" aparece?
Conclusao: Porque o locale que suas variaveis
LANG/LC_*solicitam (ex:en_US.UTF-8) nao esta gerado ou instalado naquele sistema. Ao solicitar um locale que nao existe, a glibc faz fallback para o locale C.
Um locale agrupa idioma, codificacao de caracteres e formatacao de data/numero sob um nome como en_US.UTF-8 ou ja_JP.UTF-8. Na inicializacao, um programa chama setlocale() e resolve o locale solicitado na ordem de prioridade: LC_ALL → LC_* → LANG.
Quando o nome solicitado nao existe no sistema, a glibc emite um aviso e faz fallback para o locale seguro C (POSIX). Mensagens tipicas:
# 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 padroes de "nao existe"
- O pacote
localesem si nao esta instalado (containers minimos, imagens cloud) - O pacote esta presente mas o locale nunca foi gerado (
locale-gennao executado) - O SSH encaminhou o locale do seu terminal e o servidor alvo nao tem o mesmo
- Um erro de digitacao (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 nao existe
Como encontro qual variavel esta errada?
Conclusao: Use
localepara os valores atuais e a variavel ofensora, elocale -apara a lista de locales disponiveis. Se o nome solicitado nao esta na lista, essa e a causa.
Executar locale mostra as configuracoes atuais e qual variavel e 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 e solicitado, mas a lista tem apenas locales da familia C. O nome solicitado nao aparecer em locale -a e a evidencia decisiva.
Atencao para variacoes de nome. locale -a pode imprimir na forma en_US.utf8 (minusculo, sem hifen), mas uma configuracao LANG=en_US.UTF-8 e tratada como a mesma. Entretanto, en_US (sem codificacao) e en_US.UTF-8 sao diferentes, entao verifique se o sufixo tambem corresponde.
Por que o aviso aparece via SSH?
Conclusao: O cliente SSH encaminha seu locale local com
SendEnv LANG LC_*, e o servidor aceita viaAcceptEnv. Se o servidor nao tem aquele locale, voce recebe o aviso em cada login.
Se nunca aparece localmente mas aparece toda vez que voce se conecta via SSH a um servidor, esta e quase sempre a causa. A maioria das distros vem com uma configuracao 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 sessao. Se o servidor nao tem aquele locale, setlocale falha quando o shell inicia.
Voce tem duas opcoes: instalar o locale no servidor (passos abaixo) ou parar de encaminha-lo. Para parar o encaminhamento, edite a configuracao do cliente.
# Desabilitar encaminhamento para um host em ~/.ssh/config
Host myserver
SendEnv -LANG -LC_*Para evitar o aviso de locale em uma unica conexao, envie o locale C que esta sempre presente para sobrescreve-lo. LC_ALL tem precedencia sobre todos os outros LC_* e LANG, entao ele vence mesmo quando um valor foi encaminhado.
$ LC_ALL=C ssh user@myserver
Como gerar ou instalar o locale? (Debian / Ubuntu)
Conclusao: Instale o pacote
locales, gere o locale alvo comlocale-gene defina o padrao comupdate-locale. O interativodpkg-reconfigure localesfaz o mesmo.
No Debian / Ubuntu, um locale requer dois passos: instalar o pacote e gera-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 configuracao 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 espaco para gera-los.
$ sudo dpkg-reconfigure locales
Mudancas de update-locale e /etc/default/locale so entram em vigor a partir de uma nova sessao de login. Para aplica-las ao shell atual imediatamente, faca logout e login novamente, ou defina um valor por enquanto com export LANG=en_US.UTF-8.
Corrigindo no RHEL / Fedora
Conclusao: No RHEL 8 e posterior, instale o locale via pacote
glibc-langpack-<lang>e defina o padrao comlocalectl set-locale.
No RHEL / CentOS Stream / Fedora, voce 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 e o comando comum de gerenciamento de locale em sistemas systemd, e ele escreve a configuracao 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 familia Debian que tambem tem localectl (systemd), voce pode definir o padrao com localectl set-locale tambem. Mas gerar o locale continua sendo trabalho do locale-gen, entao a ordem gerar → localectl permanece a mesma.
Um workaround rapido quando voce so quer silenciar
Conclusao: Use
export LC_ALL=Couexport LANG=C.UTF-8para mudar para um locale que certamente existe. Nao e uma correcao real, mas para o aviso instantaneamente.
Para uma execucao de script ou tarefa pontual onde voce "so quer que o aviso pare agora", aponte para um locale da familia 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 sao embutidos na glibc e funcionam em quase todo lugar sem locale-gen. Escolher C.UTF-8 mantem sequencias de bytes UTF-8 intactas enquanto usa mensagens em ingles.
LC_ALL e a variavel de maior prioridade que sobrescreve todo LC_*. Fixa-la em C forca a classificacao de caracteres e ordem de ordenacao para o locale C tambem. Colocar LC_ALL=C em um arquivo permanente (como .bashrc) convida outros bugs, entao mantenha como workaround e corrija permanentemente gerando o locale.
Se voce so quer silenciar um unico script, delimite no topo.
#!/usr/bin/env bash export LC_ALL=C.UTF-8
Checklist para prevenir recorrencia
Conclusao: Pre-gere os locales que um servidor precisa, pare forwarding SSH desnecessario e evite fixar
LC_ALLpermanentemente, e avisos de locale sao amplamente preveniveis.
| Medida | Comando / configuracao | Efeito |
|---|---|---|
| Gerar locales necessarios | sudo locale-gen en_US.UTF-8 |
Remove o nome solicitado ausente |
| Definir padrao explicito do sistema | update-locale / localectl set-locale |
Fixa o padrao por login |
| Parar forwarding SSH desnecessario | SendEnv -LANG -LC_* |
Previne importacao de locales ausentes |
| Manter workarounds locais | export LC_ALL=C.UTF-8 dentro de script |
Evita efeitos colaterais de fixacao global |
Copie e cole: diagnostico 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