首先来描述一下我遇到的问题:如下图所示在我们产品中,服务脚本放置在目录/etc/init.d中,在用命令 "service xxx start" 后,脚本中启动应用程序ice_main,ice_main进程中使用命令 "locale" 来获取当前所使用的语言。但是获取的LANG的值为空......
首先,在安装了产品的Redhat5上查看是否存在同样的问题(检查是否是前辈遗留的历史问题),结果能够正常的获取LANG的值;初步说明代码在获取当前所使用的语言的方法没有问题;
然后,在Redhat6,shell命令行里输入 "locale" , 查看结果LANG的值并不为空:
[root@rhel6_64_khm /]# locale LANG=en_US.UTF-8 LC_CTYPE="en_US.UTF-8" LC_NUMERIC="en_US.UTF-8" LC_TIME="en_US.UTF-8" LC_COLLATE="en_US.UTF-8" LC_MONETARY="en_US.UTF-8" LC_MESSAGES="en_US.UTF-8" LC_PAPER="en_US.UTF-8" LC_NAME="en_US.UTF-8" LC_ADDRESS="en_US.UTF-8" LC_TELEPHONE="en_US.UTF-8" LC_MEASUREMENT="en_US.UTF-8" LC_IDENTIFICATION="en_US.UTF-8" LC_ALL=这样问题就更加奇怪了,在我默认的知识里,shell相当于是这一系列进程的父进程,子进程应该继承父进程的环境变量。
接着,就开始进行代码审查,查看ice_main代码中是否对Redhat6平台进行了特殊处理,或者在代码中是否对环境变量进行了重新设置,结果是没有。那LANG到底在哪一步被更改了呢?
最后,当你没有任何进展的时候,就应该采用最笨的方式,从头到尾仔细检查每一个步骤。我开始从进程的源头查看,首先我们使用了命令 "service xxx start" ,这一个命令包含了三个步骤:Shell创建子进程执行service 脚本 (/sbin/service),service 脚本执行进程创建子进程执行xxx脚本,那么既然在shell中能够获取LANG的值并且不为空,那么让我们来看一下Redhat6中的/sbin/service脚本,果不其然,最后调用如下命令去执行xxx脚本:
env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ${OPTIONS}
-i, --ignore-environment start with an empty environment
那我们再一起来看看Redhat5中的/sbin/service脚本,可以看到其中虽然使用了参数'-i',但随后还是将本进程LANG的值传递给子进程,所以产品在Redhat5中执行时,可以获取非空的LANG:
env -i LANG="$LANG" PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ${OPTIONS}
这个问题解决思路也比较简单,我个人有两个建议:
1. 采用命令行 "/etc/init.d/xxx" 来调用执行脚本
2. 从文件 "/etc/sysconfig/i18n" 中读取LANG的值