tmux,乱码已成往事

我用tmux有一段时间了,工作中会用到它的「会话保持」这一功能。在「跳板机」上建一个tmux会话,然后打开多个tmux window,在每个window下ssh连接到「开发机」,这是非常普遍的开发方式。下班时我只要按bind-key + d脱离会话,电脑盖子一合就可以走人,当前机器上的多个ssh连接、打开的文档、运行的程序,都毫无「违和感」地同步「下班」。

第二天上班,我连接到「跳板机」,简单地执行2个命令,就可以重新快速挂载到昨天的tmux会话,之前建立的多个ssh连接、打开的文档、运行地程序,又都毫无「违和感」地同步「上班」,保持着昨天的状态(当然,运行着的程序没有退出的意思)。建立tmux会话时我并没有指定名称,重新挂载到会话上非常简单:

[xiaojie.zhang1@FS67 ~]$ tmux ls    // 列出当前的tmux会话, ls = list session
0: 4 windows (created Wed Nov  6 18:37:38 2013) [181x50] (attached)
[xiaojie.zhang1@FS67 ~]$ tmux attach -t 0    // 挂载到第一个会话, -t 0

然而使用过程中遇到一个屏幕显示错乱的问题,在ssh连上「开发机」后,在「开发机」上用vim打开包含有中文的代码,就会出现:
显示错乱

万能的google会告诉我在tmux的配置文件中添加2个utf8的项:

[xiaojie.zhang1@FS67 ~]$ grep utf8 ~/.tmux.conf
setw -g utf8 on
set -g status-utf8 on

添加了之后就出现了中文「乱码」。
中文乱码

这2个配置项是不能解决问题的,乱码的因素有多个的好吗!!!!

  1. 终端的编码
  2. vim的编码
  3. tmux的编码
  4. 系统的locale

对于第1点, 我使用的iterm2,使用的字符编码为Unicode(UTF-8),嗯,已经是utf8了。

对于第2点,用vim的人都知道,vim读写一个文件时,使用设置项fenc配置的编码,比如utf8;而vim显示文件内容,使用的是另一个设置项tenc配置的编码,如果这2个配置的编码不一致,就能够看到vim的乱码。我先确认vim打开文件的编码和展示都用到utf8编码,两者编码一致:

:set fenc    // 在vim命令行下
  fileencoding=utf-8    // vim命令行下的输出
:set tenc    // 同上
  termencoding=utf-8

其实,不用tmux,从「跳板机」ssh连上「开发机」,再使用vim打开任何文本,都是不会乱码的(因为vim配置了正确的编码方式)。

对于第3点,tmux添加了utf8的编码也没有效果(其实这2个是设置tmux window的好吗), tmux的显示到底是根据哪里的配置??

到了第4点,确认是系统的locale问题了,tmux依赖于这些设置。由于我是在「跳板机」上使用tmux,tmux会使用到「跳板机」上的locale参数,查看:

[xiaojie.zhang1@FS67 ~]$ locale
LANG=en_US.en
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=C

果然!!!!于是再检查「跳板机」上是否已经安装zh_cn字符集:

[xiaojie.zhang1@FS67 ~]$ locale -a | grep -i zh_cn
zh_CN
zh_CN.gb18030
zh_CN.gb2312
zh_CN.gbk
zh_CN.utf8

没让我失望,有zh_cn.utf8,添加到profile里吧:

[xiaojie.zhang1@FS67 ~]$ grep -i utf ~/.bash_profile
export LANG="zh_CN.UTF-8"
export LC_ALL="zh_CN.UTF-8"

kill掉tmux当前的会话,重新登录「跳板机」,新建一个tmux会话,再次确认tmux加载到新的locale

[xiaojie.zhang1@FS67 ~]$ tmux    // 新建一个tmux会话和窗口

[xiaojie.zhang1@FS67 ~]$ locale    // 进入tmux的窗口,再确认一次locale
LANG=zh_CN.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=zh_CN.UTF-8

tmux用到了utf8了, 这时再ssh连接到「开发机」,vim打开之前的文件,乱码已成往事,当然也不会显示错乱。

也就是说,若要「乱码」已成往事,需要4个地方的编码:

  1. 终端使用utf8编码(比如我使用iterm2,item2的终端字符集为Unicode(UTF-8) )
  2. 使用tmux的机器上(比如我这里的「跳板机」),其个人profile的locale使用utf8

     [xiaojie.zhang1@FS67 ~]$ grep -i utf ~/.bash_profile
     export LANG="zh_CN.UTF-8"
     export LC_ALL="zh_CN.UTF-8"
    

    每次登录都会export这2个环境变量,从而设置locale。

  3. 开发机」上vim设置utf8编码(linux)

     xiaojie.zhang1@log83 ~$ grep enc ~/.vimrc
     set enc=utf8
     set fencs=utf8,gbk,gb2312,gb18030,cp936
    

    vim里其实没必要设置tenc,它会从fencs列表中选一个适合的编码方式。

  4. tmux倒是可以不设置utf8



推荐一个讲解vim编码方式的普及blog: VIM乱码原因与解决方案

– EOF –

Categories: in_mac
Tags: iterm