最近遇到一台ubuntu服务器登陆时默认语言环境变量变成posix问题, 导致中文显示乱码,影响程序的正常运行
# locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=
按照常规的分析,应该是开机没有加载某个配置文件
在ubuntu系统下,语言变量一般是在 /etc/default/locale
中设置的,安装系统时选择的语言最终也会写入到这里
查看这个值发现并没有问题
cat /etc/default/locale
LANG="en_US.UTF-8"
那么另一个可以设置这个变量的就是 /etc/environment
了
在测试时,系统这个文件上并没有写入 LANG的配置,其实这也是合理的
现在最主要的问题是ssh登陆时没有加载到配置文件 /etc/default/locale
找了一会问题,还没完全解决,这时告诉同事等会再来排查问题。突然同时说问题已经解决了,
遂激动的询问是怎样解决的。
直接在 /etc/profile
里面加上 export LANG=en.US-UTF-8
尴尬了。。。 这么简单的事。。一直想着查找为什么无法加载locale文件,忘记了最简单的解决办法。下次切记~~
登陆流程获取shell,肯定会加载profile文件嘛,还有在用户家目录里面设置环境变量也是可以的
当然,上面虽然可以正常解决问题,可是具体原因并没有对症下药
后来对比了login获取shell时的环境变量 和su时获取的环境变量, 发现这两个都是正常的
查看了ssh的配置文件 /etc/ssh/sshd_config
, 其中有一句
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
按照注释看,这应该是加载本地的环境变量, 所以我把当前shell的语言变量设置成其他的,用ssh到其他电脑,果然环境变量会随着本地机器的设定而变化,然后再用login及su登陆系统, 奇怪的是系通正常设定了语言(这才应该是正常的情况)
问题到这,已经确定是ssh登陆时会有问题,而login和su登陆没有问题
简单的联想到是不是PAM模块未加载这个配置文件,一番对比,发现 /etc/pam.d/
下面的 login su sshd 并没有太大的区别 都有一句加载locale变量
# Read environment variables from /etc/environment and
# /etc/security/pam_env.conf.
session required pam_env.so # [1]
# In Debian 4.0 (etch), locale-related environment variables were moved to
# /etc/default/locale, so read that as well.
session required pam_env.so user_readenv=1 envfile=/etc/default/locale
按理说,这应该是没问题的。。。
往往,答案就隐藏在某个看不见的最安全的也是最容易发现地方,只是可惜被我忽略了
在sshd_config配置文件的最后有一个配置
UsePAM no
都已经设置成不加载PAM模块了,之前设定的语言变量肯定也不会被加载了嘛, 更改成yes后,登陆正常
再来看下曾今答案离我多近
ClientAliveInterval 3600
ClientAliveCountMax 10
#MaxStartups 10:30:60
#Banner /etc/issue.net
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
UsePAM yes
也就是在设定加载本地语言环境变量的下面。。。。
好了,现在粗略总结下系统登陆时获取shell的加载过程。排除登陆问题可以按照这些流程一一排查可能出错的地方
开机-->init程序-->获取登陆shell-->加载PAM模块-->加载/etc/profile文件-->加载用户家目录配置文件
网络的设置是在init程序的时候由/etc/init.d内文件指定,开机时会按顺序加载,作为开机自启程序
PAM模块 会加载一些环境变量
/etc/profile文件会调用一些其他设置,包括/etc/profile.d/*.conf 文件
用户家目录配置文件可以设定一些自定义变量, 比如可以设置语言为 zh_CN.UTF-8 (系统环境最好保持en_US.UTF-8)