Linux 日志里的中文全是乱码?三处编码对完账就清楚了
做运维的多少都见过这一幕:服务器上 tail 一个日志,中文全变成了问号,或者干脆是一串看不懂的符号;更迷惑的是,同一台机器上有的日志正常、有的乱,换个终端窗口看又不一样。很多人第一反应是敲一句 export LANG 了事,结果这边好了那边又乱——因为中文从"程序写出来"到"你眼睛看到",中间要过三道关卡,只修一道,当然按倒葫芦起了瓢。
把这三道关卡捋清楚:
第一处,程序写出端。应用把日志写进文件时用的编码,由程序自己决定:Java 有 file.encoding 参数,各类应用有自己的日志编码配置。写出去是 GBK,落盘的就是 GBK 的字节。 第二处,文件本体。日志文件落盘之后,编码就固定在字节里了,不会因为你后来改了什么显示设置就跟着变。 第三处,终端显示端。你用 SSH 连上去看日志,终端按当前 locale 声明的字符集去解释字节流,解释错了就是乱码。
乱码的本质就一句话:三处编码对不上账。排查照这个顺序走:
- 先看终端自己的 locale:敲 locale 命令,重点看 LANG 和 LC_ALL 两项。如果显示的是 C 或者 POSIX,说明终端环境没声明用 UTF-8,哪怕文件是好的也会显示乱。可以临时用 export LANG=zh_CN.UTF-8 验证,但别指望一句 export 包打天下。
- 再验文件的真实编码:用 file 命令,比如 file app.log,回显里写着 UTF-8 就是 UTF-8;出现 Non-ISO extended-ASCII 之类的字样,多半是 GBK、GB2312 一类的中文编码。
- 对账程序端:确认应用写日志用的编码,和团队约定统一(新项目现在基本都约定 UTF-8),该改的配置趁早改。
- 旧文件要看就转一份:用 iconv -f GBK -t UTF-8 old.log > new.log 转出一个新文件来看,原文件保持原样,方便留档比对。
- 固化环境:系统层面的字符集写进 /etc/locale.conf 这类配置,让每次登录进来都是声明好的环境,而不是靠个人备忘。
这套"对账"思路在企业环境里尤其值钱:集中日志服务器收上来几十台机器的日志,源头编码五花八门,远端看到的乱码十有八九是源头就没对齐——治本永远在写出端,不在看的人那边。这也解释了开头那个现象:同一台机器上"有的日志正常、有的乱",因为乱的那批是老应用写的 GBK,正常的那批是新服务写的 UTF-8,文件层面本来就分了家;而"换个终端窗口看又不一样",则是第三处(终端 locale)在跟着变。两个疑问都能被同一张对账表解释掉,这正是这套方法好用的地方。
贵州诚鑫致达科技在做企业中文环境的系统交付时,编码三处对账是必检项:应用写出、文件落盘、终端显示一条条过一遍,省得上线之后再回头翻旧账。你在生产环境里见过哪些哭笑不得的乱码现场?评论区聊聊。