首页/系统与基础设施/自动化运维速查/编码与字符集导致的乱码
排障与安全50 条

编码与字符集导致的乱码

乱码由字节与解释方式不匹配引起,链路上远程程序输出、传输转换与终端解析三处各有编码假设;排查先确定真实编码再动手转换,跨平台自动化应统一脚本、执行环境与采集解析三处的编码设定。

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​​‌​‌‌​‌​‌‌​​​‌‌​‌‌​‌​​​​‌‌​​​​‌​‌‌‌​​‌​​‌‌‌​​‌‌​‌‌​​‌​‌​‌‌‌​‌​​​​‌​‌‌​‌​‌‌​​‌‌‌​‌‌​​​​‌​‌‌‌​​‌​​‌‌​​​‌​​‌‌​‌‌​​​‌‌​​‌​‌​‌‌​​‌​​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌‌​​​​​‌‌‌​‌​‌​‌‌‌​‌​​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

乱码是字节与解释方式不匹配

远端执行命令后输出乱码,本质不是数据错了,而是同一段字节被用错了编码去解释。链路上至少有三个环节各自持有编码假设:远程程序的输出编码、传输过程中是否被转换、以及本地终端或日志系统的解析编码。只要其中一环与实际字节不一致,就会显示为乱码。排查的入手点也就很明确——先确定这段字节真实是什么编码,再检查谁在用另一种编码解释它。

基本信息

适用对象Linux 与 Windows 主机的终端输出、日志、脚本执行
关键变量语言与区域设置相关环境变量,决定默认编码
常见错配远端按本地编码输出、接收端按统一编码解析
检测手段文件编码探测工具与十六进制查看
权限要求查看与修改系统级语言设置需 root

典型错配场景

  • 远端输出为本地编码:中文环境下默认输出不是统一编码时,统一编码终端会显示乱码
  • 环境变量未传递:登录后远端默认编码与服务端配置不符,脚本输出随之变化
  • 日志采集器假定编码:采集过程按统一编码解析,遇到其他编码就出现替换字符
  • 换行符差异:跨平台脚本文本中的回车符会污染输出,表现为每行末尾多余符号
  • 数据库连接字符集:客户端与服务端字符集不一致时,写入的中文变成问号或乱码
  • 命令输出重定向:非交互执行时编码假设与交互终端不同,同一命令结果不一致

定位与转换

定位与转换
locale                        # 当前会话的语言与编码设置
locale -a | grep -i utf       # 系统已生成哪些区域设置
file -i report.csv            # 探测文件声明的编码
ticonv -f gb18030 -t utf-8 old.csv > new.csv   # 明确源编码后再转换
iconv -f gb18030 -t utf-8 -c old.csv > new.csv  # 无法转换的字符直接丢弃
od -c out.txt | head -5       # 看真实字节,确认是否有回车符
LANG=C.UTF-8 command 2>&1     # 单次执行时固定编码
PYTHONIOENCODING=utf-8 python3 script.py  # 脚本输出编码单独指定

表现与推断

表现可能的编码关系下一步
中文变问号写入侧不支持该字符统一为支持多字节的编码
中文变方块或问号菱形解析侧遇到无法解释的字节探测真实编码后重新解释
每行末尾多一个符号换行符跨平台差异转换行结束符或改用无转换模式
参数能过但记录出错客户端与服务端字符集不一致核对连接字符集与表定义
同一命令结果不同交互与非交互的编码假设不同固定执行环境的编码
转换的前提是知道源编码。用错误的源编码做转换会得到另一堆乱码,甚至造成不可逆的字符丢失,因此应先探测或回溯数据的产生方式,再动手转换;无法确定编码时保留原始文件不动。
跨平台自动化里,统一使用不带本地化假设的编码最省事:脚本文件本身、执行环境变量与日志采集解析三处保持一致,可以避免绝大多数间歇性乱码。

易错点

  • 随便试一种源编码就转换:源编码判断错误会让数据进一步损坏,且很难还原
  • 只改终端显示设置:数据本身若已是错误编码,改显示只会换个样子,不解决根因
  • 忽略非交互执行的编码差异:手工运行正常、定时任务乱码,多因执行环境不同
  • 用替换字符掩盖问题:字符丢失后无法恢复,应优先修好链路而不是强行替换
  • 跨平台传输不做换行处理:多余回车符会破坏下游解析,表现为字段错位

数据来源与参考

  • Unicode 标准附件:UTF-8 编码
  • Linux 手册页:locale(1)、iconv(1)
  • MySQL 官方文档:字符集与连接字符集

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/automation/encoding-charset-garbled-output.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​​‌​‌‌​‌​‌‌​​​‌‌​‌‌​‌​​​​‌‌​​​​‌​‌‌‌​​‌​​‌‌‌​​‌‌​‌‌​​‌​‌​‌‌‌​‌​​​​‌​‌‌​‌​‌‌​​‌‌‌​‌‌​​​​‌​‌‌‌​​‌​​‌‌​​​‌​​‌‌​‌‌​​​‌‌​​‌​‌​‌‌​​‌​​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌‌​​​​​‌‌‌​‌​‌​‌‌‌​‌​​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​