locale命令显示当前shell进程的locale设置,非系统全局值;修改配置文件未生效因未重新登录、未source或用户级设置覆盖,且需确保目标locale已生成并正确配置环境变量作用域。

locale 命令显示的是什么,为什么改了配置文件却没生效
它显示的是当前 shell 进程的 locale 设置,不是系统全局默认值,更不是登录后自动继承的值。改了 /etc/default/locale 或 /etc/locale.conf 后不生效,大概率是因为没重新登录、没 source 配置、或用户级设置覆盖了系统级设置。
- Debian/Ubuntu 系统读
/etc/default/locale(只影响新登录的 shell),但需要sudo update-locale才写入生效,直接编辑不触发重载 - RHEL/CentOS/Fedora 用
/etc/locale.conf,改完需重新登录,source /etc/locale.conf对当前 shell 无效(因为它是 systemd 的配置文件,不是 shell 脚本) - 用户家目录下的
~/.bashrc或~/.profile里如果写了export LANG=...,会无条件覆盖系统设置 -
locale -a | grep zh_CN先确认目标 locale 是否已生成,没生成就改了也白搭
生成 zh_CN.UTF-8 locale 的关键步骤和常见失败原因
很多系统默认不生成所有 locale,尤其最小化安装的服务器。光改 LANG 没用,必须先确保对应 locale 实际存在。
- Debian/Ubuntu:运行
sudo dpkg-reconfigure locales,空格选中zh_CN.UTF-8,回车确认;或者手动编辑/etc/locale.gen取消注释zh_CN.UTF-8 UTF-8行,再执行sudo locale-gen - RHEL/CentOS:用
sudo localedef -c -i zh_CN -f UTF-8 zh_CN.UTF-8,注意-c参数能提前报错(比如 glibc 缺失中文支持),避免静默失败 - 失败典型现象:
locale: Cannot set LC_ALL to default locale: No such file or directory—— 就是 locale 没生成,不是环境变量写错了 - 生成后务必用
locale -a | grep zh_CN.UTF-8确认输出存在且拼写完全一致(大小写、点号、连字符都不能错)
LANG、LC_ALL、LC_MESSAGES 这几个变量到底谁说了算
LC_ALL 是绝对优先级最高的,只要它非空,其他所有 LC_* 和 LANG 全部被忽略。这是最常被踩的坑:临时调试时设了 LC_ALL=C,忘了清掉,后面怎么改 LANG 都没用。
- 日常建议只设
LANG,让各子类(LC_TIME、LC_NUMERIC等)自动继承;需要局部调整时单独设对应LC_*变量 -
LC_ALL应仅用于临时命令行调试,比如LC_ALL=C ls强制英文输出,绝不该写进配置文件 - 检查冲突:运行
locale,如果所有值都等于C或POSIX,但LANG显示的是zh_CN.UTF-8,基本就是LC_ALL在背后生效了 - 排查顺序:先
unset LC_ALL,再看locale输出是否符合预期,再决定是否要持久化
SSH 登录后 locale 仍是 C,但本地终端正常怎么办
SSH 默认不转发 locale 环境变量,服务端也不会自动从用户配置加载——这是设计行为,不是 bug。所以即使你本地 LANG=zh_CN.UTF-8,连过去还是 C。
- 客户端解决:在本地
~/.ssh/config对应 Host 块里加SendEnv LANG LC_*;服务端需确保/etc/ssh/sshd_config有AcceptEnv LANG LC_*(默认通常注释掉了,要取消注释并sudo systemctl restart sshd) - 服务端兜底:在
/etc/profile.d/lang.sh(或/etc/profile)里追加export LANG=zh_CN.UTF-8,这样所有登录 shell 都会继承 - 注意:
LC_ALL不会被 SSH 转发,就算写了SendEnv LC_ALL也无效,协议层面禁止 - 验证是否成功:SSH 连入后立刻运行
locale | grep -E '^(LANG|LC_ALL)=',确认值是你设的,而不是C










