linux终端乱码需同时满足:系统已生成zh_cn.utf-8 locale(用locale -a验证)、lang/lc_ctype正确设置、终端模拟器及ssh客户端均启用utf-8编码,缺一不可。

Linux终端从GBK转为UTF-8,不是简单改一个变量就能生效的。核心问题是:LANG 和 LC_CTYPE 必须指向已生成的 UTF-8 locale,且终端模拟器本身要启用 UTF-8 编码,缺一不可。
检查当前 locale 是否支持 zh_CN.UTF-8
先确认系统有没有真正安装并生成 zh_CN.UTF-8,而不是只改了环境变量:
- 运行
locale -a | grep zh_CN,如果输出里没有zh_CN.UTF-8(只有zh_CN.GBK或空),说明 locale 文件尚未生成 - 运行
locale,看LANG和LC_CTYPE是否为zh_CN.GBK或C—— 这类值即使终端设成 UTF-8 也照样乱码 -
locale -i不是标准命令,别被误导;用locale -a才是查真实可用项的正确方式
生成 zh_CN.UTF-8 locale 并设为默认
Ubuntu/Debian 系统用 locale-gen,CentOS/RHEL 用 localectl 或手动配置,但流程本质一致:
- 编辑
/etc/locale.gen,取消注释行:zh_CN.UTF-8 UTF-8(注意不是zh_CN.GBK) - 执行
sudo locale-gen—— 这步必须做,否则locale -a永远看不到它 - 设为系统默认:
sudo localectl set-locale LANG=zh_CN.UTF-8(systemd 系统);旧系统如 CentOS 6 则写入/etc/sysconfig/i18n或/etc/default/locale - 改完不重启也能立即生效:在当前终端运行
source /etc/profile或重新登录
终端模拟器和 SSH 客户端必须同步设为 UTF-8
即使系统 locale 正确,GNOME Terminal、Xshell、Windows Terminal 等若自身编码没设对,照样显示方块或问号:
- GNOME Terminal:右键 → Preferences → Profile → Text → Character encoding → 选
Unicode (UTF-8) - Xshell:文件 → 属性 → 终端 → 编码 → 选
UTF-8;同时字体要选含中文的,比如WenQuanYi Zen Hei或Noto Sans CJK SC - SecureCRT:
Options → Session Options → Translation → Remote character set设为UTF-8(不是 “Use font encoding”) - Windows Terminal 连 WSL:确保 JSON 配置中
"locale": "zh_CN.UTF-8"且"fontFace": "Cascadia Code"已安装并含 CJK 字形
为什么改了 LANG 还是乱码?常见坑点
很多用户卡在这一步:明明 echo $LANG 输出 zh_CN.UTF-8,但 ls 列出的中文名还是乱码。原因往往藏在这些地方:
-
LC_ALL被设为非 UTF-8 值(如LC_ALL=C),它会强制覆盖所有其他LC_*变量 —— 检查locale输出中LC_ALL是否为空 - SSH 连接时客户端未传递 locale:PuTTY 要勾选
Connection → Data → Enable UTF-8;OpenSSH 客户端需确认SendEnv LANG LC_*在/etc/ssh/ssh_config或~/.ssh/config中启用 - 某些老旧服务(如 systemd-journald)或容器环境会忽略用户级
~/.bashrc中的export,必须用localectl或系统级配置才生效 - 文件本身是 GBK 编码保存的(比如 Windows 下写的脚本),
cat出来当然乱码 ——iconv -f GBK -t UTF-8 file.sh才能正确查看
最关键的其实是顺序:先确保 zh_CN.UTF-8 被 locale-gen 真正生成,再设 LANG,最后调终端和 SSH 设置。漏掉任意一环,都会让前面所有操作白费。











