[Feelings & Sharing] (水)记一次配置开发环境导致的系统语言变更的问题及其解决过程
Tofloor
poster avatar
geebytes
deepin
2024-03-02 11:00
Author

背景

  • 今早重启之后系统语言就突然变成了英文,之后去设置里面将语言切换为中文,重启之后依然是英文
    image.png
  • 此时查看系统环境变量,发现中文语言包还在,但此时的系统参数仍为英文语言参数,真是见鬼了
    image.png
  • 系统信息,fastfetch却显示locale是中文,就很诡异
    image.png

排查

本来整理完上面的信息,这帖子应该是要发到论坛的问题求助的,准备提提交的时候发现没有提交系统日志,于是我就去看看了系统自带日志收集,没有发现关联的信息。第一次查看日志没关联信息,于是我重复了语言切换的操作,将日志级别设置成ALL ,发现日志显示"setLang is "zh_CN.UTF-8""且"setLang success",说明操作已经成功了。

基于前面日志的分析,可以基本判断不是操作系统设置的问题。那问题出在呢?首先要确定linux是如何实现语言的切换的。

Linux 系统的语言设置由环境变量决定,主要是通过设置 LANG 和其他 LC_* 类型的环境变量来实现的。基于这条信息,再回头看前面提到的一些系统变量确实是英文参数。因为我平时办公和开发都是用这个系统环境,是不是昨天有什么操作修改了系统的环境变量?于是我决定看看这些语言相关的环境变量是不是被写入了环境变量配置文件:

  • cat ~/.zshrc | grep LANG
    
  • cat ~/.bashrc|grep LANG
    
  • cat /root/.bashrc | grep LANG
    
  • sudo cat /etc/profile | grep LANG
    

上面的几条命令输出都为空,到这里我一度认为系统的环境变量配置文件没有被修改,后面想到这些配置文件是可以加载第三方的配置或脚本修改操作系统的环境变量的,于是我先看了/etc/profile.d目录文件下是否包含关键词"LANG"。

grep "LANG" /etc/profile.d/*

果然输出了下面的信息

/etc/profile.d/utf8.sh:export LANG="en_US.utf8"
/etc/profile.d/utf8.sh:export LANGUAGE="en_US"

到这里已经接近真相了,现在的问题是这个脚本有没有被加载,于是分析了/etc/profile文件发现了下面的代码,发现脚本确实被加载,破案了!

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done

接着看了一下/etc/profile.d/utf-8.sh的内容,发现它只干了一件事,修改操作系统语言。

export LANG="en_US.utf8"
export LC_ALL="en_US.utf8"
export LANGUAGE="en_US"

ok,接下来只需要移除该文件然后重启看看效果,为了以防万一,习惯性备份一下再重启

sudo mv /etc/profile.d/utf8.sh /etc/profile.d/utf8.bak&&reboot

重启之后发现系统语言恢复正常

溯源

那么到底是谁添加了这个脚本?既然能写入这个目录就需要sudo命令,于是决定看看昨天做了哪些sudo操作,这里用history命令看一下,没发现可疑的地方。

history|grep sudo

难道是系统更新的问题?因为昨天周五刚好更新了系统,既然是写入了固定的文件,其他用户应该也会有同样的问题,于是到论坛浏览看看有没有相关的的反馈,看了一圈并没有发现有想关的反馈。想想也是作为程序员,我的同行应该不会犯这种错误,直到后来我发现我的是判断对一半错一半。

接着回想了一下昨天的工作内容,因为最近正在看redis 布隆过滤器实现的源码,所以需要编译调试RedisBloom的代码,想起来在编译RedisBloom之前,准备编译环境的时候按照README要求进行下面的操作,这个过程需要输入密码,说明有sudo的操作。

./sbin/setup

基于上面的分析和怀疑我决定以"utf8.sh"作为关键词直接搜索这个项目源代码,果然发现就是这个项目的脚本写入了这个文件

image.png

代码如下

create_utf8_profile_script() {
	local profile_d=`get_profile_d`
	if [[ -n $1 ]]; then
		local language="$__language"
	fi
	cat <<-EOF > $profile_d/utf8.sh
		export LANG="${__language}.${__utf8}"
		export LC_ALL="${__language}.${__utf8}"
		EOF
	if [[ $FORCE == 1 || -z $LANGUAGE ]]; then
		cat <<-EOF >> $profile_d/utf8.sh
			export LANGUAGE="${__language}"
			EOF
	fi
}

到这里问题就解决了。该说不说这个脚本也太坑了!为啥需要持久化这些环境变量而且还是直接修改系统级的文件。

总结

因为昨天刚好更新系统,deepin差点背锅

Reply Favorite View the author
All Replies
liwl
deepin
2024-03-02 14:08
#1
像你这么愿意折腾的不多了
Reply View the author
神末shenmo
deepin
Spark-App
2024-03-03 14:14
#2

看来有些脚本就是不负责任地往系统里拉屎啊

Reply View the author
阿尼樱奈奈
Moderator
2024-03-03 15:55
#3
like
Reply View the author
乾豫恒益
deepin
2024-03-04 08:38
#4

yeah yeah

Reply View the author