OS X Terminal: -bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory Fix

前言

闲来无事,安装了CentOS虚拟机,然后尝试了下ssh登录,结果就遇到了标题上所遇到的错误,特此进行整理。

现场还原

1
2
3
4
5
6
7
ShaoxueerdeMac:comee.github.io comee$ ssh root@10.0.2.152
root@10.0.2.152's password:
Last login: Wed Dec 16 16:00:59 2015 from 10.0.2.7
-bash: 警告:setlocale: LC_CTYPE: 无法改变区域选项 (UTF-8): 没有那个文件或目录
[root@localhost ~]# ls
anaconda-ks.cfg ?????? ?????? ?????? ?????? ?????? ?????? ?????? ??????
[root@localhost ~]#

可以看到,在浏览中文时已经出现乱码了,修复后的效果如下:

1
2
3
4
5
6
ShaoxueerdeMac:~ comee$ ssh root@10.0.2.152
root@10.0.2.152's password:
Last login: Wed Dec 16 16:08:48 2015 from 10.0.2.7
[root@localhost ~]# ls
anaconda-ks.cfg 公共 模板 视频 图片 文档 下载 音乐 桌面
[root@localhost ~]#

修复后,中文已经可以正常显示了。

这个问题的出现和OpenSSH server以及OS X ssh terminal client都有关系,所以也就有多种修复方法。

解决方案

方案一:如果你使用的是苹果的Terminal程序

1
Terminal > Preferences > Profiles > Select Terminal type such as Basic (default) > Advanced tab

Terminal

然后重启 终端程序,再次使用ssh登录远程服务器就OK了。

方案二:阻止OpenSSH将客户端的LC_*变量发送给远程服务器

编辑/etc/ssh/ssh_config 或者 /etc/ssh_config 文件:

1
2
3
4
5
6
7
8
ShaoxueerdeMac:~ comee$ cd /etc
ShaoxueerdeMac:etc comee$ ls | grep ssh
ssh
ShaoxueerdeMac:etc comee$ cd ssh
ShaoxueerdeMac:ssh comee$ ls | grep ssh
ssh_config
sshd_config
ShaoxueerdeMac:ssh comee$ sudo vi ssh_config

删除下面的配置,或者像下面这样注释掉:

1
# SendEnv LANG LC_*

保存变更后的文件,然后就发现OK了。

方案三:在远程服务器上安装缺失的locale

使用localedef命令就可以完成(根据提示进行解决):

1
localedef -i en_US -f UTF-8 en_US.UTF-8

理论

和国际化有关,涉及到的库为glibc,可以使用下面的命令查看当前终端上glibc支持的locales。

1
locale -a

然后可以使用下面的命令查看当前系统的设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ShaoxueerdeMac:~ comee$ printenv
TERM_PROGRAM=Apple_Terminal
SHELL=/bin/bash
TERM=xterm-256color
TMPDIR=/var/folders/tr/nx0vgn050dv8rwllv976c5480000gn/T/
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.PbivyAvuMD/Render
TERM_PROGRAM_VERSION=361.1
TERM_SESSION_ID=102DAF89-43E8-4881-9B4D-161A283FF54D
USER=comee
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.fqIkSAZ8zC/Listeners
__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
PWD=/Users/comee
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
SHLVL=1
HOME=/Users/comee
LOGNAME=comee
LC_CTYPE=UTF-8
_=/usr/bin/printenv
ShaoxueerdeMac:~ comee$ echo "$LC_CTYPE"
UTF-8
ShaoxueerdeMac:~ comee$

上面的命令输出结果显示了当前locale使用的编码,客户端上的ssh会将其LC*环境变量发送给服务端的sshd服务器。换句话说,SSH will try to set every LC* variable you have set on your local OSX system on the remove server too.