故事起因
一个朋友有一个openfire(开源即使通信工具)服务器,openfire是java写的,当然也就需要jdk环境了。服务器的系统是CentOS6,自己写了一个启动openfire的脚本/etc/init.d/openfire,然后注册为service可以管理的服务,但是在启动时遇到一个小问题,使用/etc/init.d/openfire start|stop|status都可以正常使用,但是使用service openfire start却无法启动openfire。了解service的都知道,service openfire start其实就是执行/etc/init.d/openfire脚本。那么为什么同一个脚本直接执行可以运行,使用service就不行了呢?
这里直接说结果吧,是由于直接执行脚本跟service执行在环境变量使用上有差别。
上面说了,由于openfire是java写的,所以需要jdk,并且需要定义java的环境变量,下面是定义好的java环境变量。
1 2 3 4 |
root@locahost:~ # cat /etc/profile.d/jdk.sh export JAVA_HOME=/usr/lib/jdk1.8.0 export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH export CLASSPATH=$CLASSPATH:.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib |
正常echo输出是没有问题的。
1 2 |
[root@www ~]# echo $JAVA_HOME /usr/lib/jdk1.8.0 |
然后我们定义一个system V的脚本
1 2 3 4 5 6 7 8 9 |
[root@www ~]# cat /etc/init.d/openfire #!/bin/bash # # chkconfig: - 75 15 # description: test echo $JAVA_HOME echo $PATH echo $LANG |
1 2 |
[root@www ~]# chmod +x /etc/init.d/openfire [root@www ~]# chkconfig --add openfire |
此及脚本主要输出环境变量,其中JAVA_HOME是我们自定义的,PATH和LANG是系统定义的。然后分别执行脚本和service命令看输出结果。
1 2 3 4 5 6 7 |
[root@www ~]# /etc/init.d/openfire start /usr/lib/jdk1.8.0 /usr/lib/jdk1.8.0/bin:/usr/lib/jdk1.8.0/jre/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin en_US.UTF-8 [root@www ~]# service openfire start /sbin:/usr/sbin:/bin:/usr/bin |
根据执行结果可以看到,直接执行脚本时,定义的三个变量都可以正常输出。但是使用service执行时,只输出了那么一点点。
现在可以说明使用service命令时,openfire由于无法读到java的环境变量,导致程序无法运行起来。
查了一下service的手册,可以了解service的一些细节:service运行指定服务(称之为System V初始脚本)时,把大部分环境变量去掉了,只保留TERM和少数变量,并且把当前路径置为/,也就是说是在一个可以预测的非常干净的环境中运行服务脚本。这种脚本保存在/etc/init.d目录中,它至少要支持start和stop命令。
所以,当把一个shell脚本放入到service中时,需要设定好PATH等环境。