一、掉进坑里
最近公司内部的一台测试服务器(CentOS6.5),因为安装某软件需要升级glibc库,glibc是linux的一个核心库,如果直接替换升级原有版本,可能出现无法预料的异常(比如大面积出现命令不能运行)。 于是手动升级安装了glibc-2.14,参考分享Centos6.5升级glibc过程 去官网下了个glibc-2.14的tar包,按照上面的步骤编译安装:
$ mkdir build // 在glibc-2.14目录下建立build文件夹
$ cd build // 进入build目录
$ ../configure --prefix=/opt/glibc-2.14 // 注意:配置glibc并设置当前glibc-2.14安装目录
$ make && make install // 编译安装glibc-2.14库
修改了/lib64/libc.so.6的软连接指向,程序可以正常运行,但中文出现了乱码问题。
于是呼,按照自己的经验和网上大多数N人的说法,认为这个简单,重新设置一下语言不就搞定了吗?
说干就干,在Shell中运行locale,出现如下错误:
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
注:以上错误不仅出现在手动运行locale命令时,而且每次ssh远程登录进shell时都会出现。
二、挣扎无果
为解决以上问题,大量度娘和G狗,尝试过以下方法,问题依旧。 使用如下命令:
export LANG="en_US.utf8"
可以修改环境变量LANG,修改之后立即生效,当时当系统重新启动时便会又变成原来的语言
另外两种修改语言的方法:
1.配置如下文件:
vi /etc/sysconfig/i18n
将原来的配置如:
LANG="zh_CN.utf8"
修改为
LANG="en_US.utf8"
保存之后不会立即生效,而是要重启之后生效。
三、青春的冲动
焦头烂额之时,出去smoking了一下,看来还是要回到问题的本质,既然出现了 No such file or directory错误,说明应该是我们配置了某种不存在或者系统不支持的locale,比如上面解决办法中的通过个修改语言LANG=”en_US.UTF-8”,将locale设置成了zh_CN.UTF-8,而操作系统在通过配置去初始化本地化环境的时候,没有找到相应的语言包(其实不只是语言包,locale还包括时区、货币度量等), 即OS找不到对应的locale文件,想明白这个问题就好办了。
先使用locale命令看看系统中有没有这个locale
[****@****** bin]# locale -a|grep en_US
en_US
en_US.iso88591
en_US.iso885915
en_US.utf8
一看傻眼了,里面有en_US.utf8,也就是说OS是支持将locale配置成en_US.utf8的,那为什么还是出现如下错误:
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
四、柳暗花明
是不是忽略了什么,再次回到原点审视。突然,想到了一个问题:我们重新安装了一个新的glibc库,而不是覆盖升级,也就是说系统中目前至少有两个locale命令,CentOS如何知道用哪个?
会不会是用了我们新装的/opt/glibc-2.14/bin/locale,而不是系统默认的/usr/bin/locale,用下面的命令很容易验证这个想法:
[****@****** bin]# /opt/glibc-2.14/bin/locale -a
C
POSIX
果然,这个locale只支持C和POSIX,而没有en_US.utf8,所以如果我们将locale配置成en_US.utf8,自然会报No such file or directory错误。
问题又来了,/opt/glibc-2.14/bin/locale命令所列举的本地化locale语言包,是从哪里来的?是通过配置文件?还是直接读取某个目录里面的文件? 当然如果去看源代码很容易找到上面问题的答案,因为俺比较懒,便大胆猜测:应该是从某个目录里面读取的,这个目录里面应该有系统所支持的所有的locale文件。这样猜测是源于错误消息是“没有这样的文件或目录”。
为了找到这个目录的位置,想到了strings命令,直接使用如下命令:
[****@****** bin]# strings /opt/glibc-2.14/bin/locale|grep locale
setlocale
/locale.
locale (GNU %s) %s
/opt/glibc-2.14/lib/locale
/opt/glibc-2.14/share/locale
all-locales
/opt/glibc-2.14/lib/locale/locale-archive
locale: %-15.15s archive: /opt/glibc-2.14/lib/locale/locale-archive
locale: %-15.15s directory: %.*s
Cannot set LC_CTYPE to default locale
Cannot set LC_MESSAGES to default locale
Cannot set LC_COLLATE to default locale
Cannot set LC_ALL to default locale
Write names of available locales
Get locale-specific information.
果然上面出现了一个路径/opt/glibc-2.14/lib/locale/locale-archive,通过名字很容易猜出这个很可能就是locale命令去读取所有被支持的locale目录(/或归档文件)位置。
五、问题KO
ls一下上面那个目录,的确里面是空的,没有locale-archive这个归档文件。
[****@****** bin]# ll /opt/glibc-2.14/lib/locale/
现在解决办法就很简单了,直接将/usr/bin/locale这个locale命令使用的locale-archive文件copy到/opt/glibc-2.14/lib/locale/locale-archive即可
[****@****** bin]# cp /usr/lib/locale/locale-archive /opt/glibc-2.14/lib/locale/locale-archive
可能有小伙伴会问了,你怎么知道/usr/bin/locale使用的locale文件目录是/usr/lib/locale/locale-archive,答案很简单:度娘一把,很容易查到。
copy完成后,exit会话,重新登录进来,再运行/opt/glibc-2.14/bin/locale命令,未出现No such file or directory错误了,而且之前的乱码问题也解决了。
六、后记
上面记录一次了笔者自己解决centos 6.5环境下手动安装glibc库后出现的乱码问题,过程中涉及到一些关于locale的原理知识,也顺便了解了一下。 By the way,上面猜测的/opt/glibc-2.14/bin/locale命令locale读取路径,后来也的确看一下locale.c源码,证实的确是从/opt/glibc-2.14/lib/locale/locale-archive读取的(当然还有其他的读取位置)。
转载自:https://blog.csdn.net/guitar___/article/details/77651983