使用service启动tomcat服务导致的log4j输出文字异常

在Amazon的EC2上,用Amazon官方Linux AMI创建了一个实例,安装并配置tomcat,部署应用。
偶然一次使用service tomcat start启动服务,发现log4j输出的log中的日文字符统统变成了问号「?」。但使用/etc/init.d/tomcat启动服务却一切正常。

以前余就知道service方式启动服务会忽略掉很多环境变量,比如JAVA_HOME。
使用man命令查看帮助
[root]# man service

ENVIRONMENT
       LANG, TERM
              The only environment variables passed to the init scripts.

说是service会保留LANG和TERM两个环境变量。(事实上PATH环境变量也会传递进去)

仔细查看service脚本,却完全不是这回事。

[root]# which service
/sbin/service
[root]# vim /sbin/service

cd /
while [ $# -gt 0 ]; do
  case "${1}" in
    --help | -h | --h* )
       echo "${USAGE}" >&2
       exit 0
       ;;
    --version | -V )
       echo "${VERSION}" >&2
       exit 0
       ;;
    *)
       if [ -z "${SERVICE}" -a $# -eq 1 -a "${1}" = "--status-all" ]; then
          cd ${SERVICEDIR}
          for SERVICE in * ; do
            case "${SERVICE}" in
              functions | halt | killall | single| linuxconf| kudzu)
                  ;;
              *)
                if ! is_ignored_file "${SERVICE}" \
                    && [ -x "${SERVICEDIR}/${SERVICE}" ]; then
                  env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" status
                fi
                ;;
            esac
          done
          exit 0
       elif [ $# -eq 2 -a "${2}" = "--full-restart" ]; then
          SERVICE="${1}"
          if [ -x "${SERVICEDIR}/${SERVICE}" ]; then
            env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" stop
            env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" start
            exit $?
          fi
       elif [ -z "${SERVICE}" ]; then
         SERVICE="${1}"
       else
         OPTIONS="${OPTIONS} ${1}"
       fi
       shift
       ;;
   esac
done

if [ -f "${SERVICEDIR}/${SERVICE}" ]; then
   env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ${OPTIONS}
else
   echo $"${SERVICE}: unrecognized service" >&2
   exit 1
fi

本来系统的默认locale是en_US.UTF-8,也即环境变量$LANG的值为en_US.UTF-8,
/etc/init.d/tomcat start方式启动tomcat,除非在启动脚本中干啥坏事,否则全部的环境变量都会保留,log4j输出不会有错误

env -i命令是创建一个空白的运行环境,如果不主动传入参数,所有的环境变量都会被忽略。
Amazon官方Linux AMI的service脚本用env -i创建启动环境时,却删掉了LANG=”$LANG”,也即locale变成了POSIX,log4j输出时按POSIX输出,非ASCII字符全变成了问号

Amazon官方Linux AMI修改自CentOS,但人家CentOS的service脚本LANG保留得好好的
ubuntu的service脚本文件是/usr/sbin/service,LANG同样传递了进去

为了排查这个错误,花了一下午时间,狠命死抽Amazon

改正方法很简单,补回LANG环境变量即可

env -i LANG="$LANG" PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ...

一共四处地方

2011年10月3日 | 归档于 技术
本文目前尚无任何评论.

发表评论

XHTML: 您可以使用这些标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
:wink: :-| :-x :twisted: :) 8-O :( :roll: :-P :oops: :-o :mrgreen: :lol: :idea: :-D :evil: :cry: 8) :arrow: :-? :?: :!: