跳至主要内容

改写一段自启动服务的脚本

用了一年多的Ubuntu,平时写脚本读脚本渐渐的已经习惯了Debian风格的函数调用,最近因为工作需要,在Fedora服务器上要加入一个自启动服务,花了两天时间重写一段脚本。po上来以备有相同需要的筒子参考。

无论是在Ubuntu还是Fedora下面,我用的shell都是bash,所以基本的命令都是想通的。只是在/etc/init.d里面有几个函数族不太一样。以下先将最终写好的Fedora脚本贴出来,然后再罗嗦几句……

# !/bin/bash
#
# chkcofig: 35 -80 50
# Description: Company Application Server Implementation
#

# Check the privilege
if [ `id -u` -ne 0 ]; then
echo "You need root privileges to run this script"
exit 1
fi

# Source function library.
. /etc/init.d/functions
. /lib/lsb/init-functions

# Configurations (could be defined in /etc/sysconfig/mvas)
APP_NAME=mvas
PID_FILE=/var/run/${APP_NAME}.pid
LOCK_FILE=/var/lock/subsys/${APP_NAME}
CATALINA_HOME=/usr/share/tomcat5
APPSERVER_HOME=${MVAS_HOME-/etc/comp/privaty}

pidof_mvas() {
local pids=`pidof /usr/bin/java`
echo "pid = $pids"
for ii in $pids; do
echo "testing $ii "
if [ -d /proc/$ii ]; then
hit=`ps ax | grep $ii | grep appsrv\/conf`
[ -n "$hit" ] && export PID_MVAS=$ii || echo "$ii is not target"
fi;
done
}

start() {
echo -n "Starting App Service..."
su -l tomcat -c "/usr/bin/java \
-Dlog4j.configuration=file://${APPSERVER_HOME}/conf/log4j.properties \
-cp ${CP} com.comp.appserver.Bootup >/dev/null 2>&1 &"
RETVAL=$?
echo
# clean the env-var $PID_MVAS first
unset PID_MVAS
# wait till the JVM successfully load all classes
sleep 3
# Get the pid of the JVM process
pidof_mvas
if [ -n $PID_MVAS ]; then
echo -n "Target found: \$PID_MVAS = **${PID_MVAS}**"
echo $PID_MVAS > $PID_FILE
echo
else
echo "error matching $PID_MVAS"
fi;
return $RETVAL
}

stop() {
echo -n "Stopping App Service..."
killproc -p $PID_FILE /usr/bin/java
RETVAL=$?
echo
return $RETVAL
}

restart() {
stop
start
}

reload() {
stop
start
}

# Collect all JAR files into classpath $CP
for i in `find /usr/share/tomcat5/shared/lib -name \*.jar`
do
CP=$i:"$CP"
done

# Main entry
case "$1" in
start)
start
;;

stop)
stop
;;

restart)
log_msg "Restarting App Service..."
restart
;;

*)
log_msg "Usage: /etc/init.d/mvas {start|stop|restart}"
exit 1
esac

exit 0

读脚本要先从最后一段开始,这里是入口点,一个switch-case调用startstoprestart等不同的子例程(subroutine)。无论是在Ubuntu上,还是在Fedora上,这段入口的结构都是大致相同的。

start()

这段函数负责启动服务。前三行是一个惯例写法——先echo -n输出一行提示信息,但是不换行,接着后台执行su以tomcat用户启动一个shell并调用JVM。注意这里将stdout和stderr都重定向到了 /dev/null (也就是忽略所有的输出)。实际上程序内部使用了log4j的配置文件来生成日志文件到某个特定的目录。

在启动了JVM之后,调用pidof_mvas获取JVM的Porcess ID (进程标识符),即pid。通常Linux上运行的JVM可能不止一个,例如WEB包容器tomcat、自定义的Java服务程序。所以仅仅使用 pidof 来查找进程是不可靠的。函数pidof_mvas()利用pidof命令获得所有 /usr/bin/java 程序的运行进程的pid,再使用 grep 过滤特定的字符以找出匹配的进程。如果找到了目标进程,就将起pid设置到环境变量 $PID_MVAS 中,以供后续程序使用。这也就是为什么start()在调用pidof_mvas()之前,必须先unset PID_MVAS的原因。

找到了pid之后,就将它的值输出到 /var/run/$PID_FILE 中。这是启动服务的惯例做法,通常有2个文件是比较常用的——一个是 /var/run/${service}.pid ,另一个是 /var/locks/subsys/${service} 。这两个文件通常都是在服务进程启动的时候就被创建的,到了服务进程将停止的时候被删除。


stop()

接着看看stop()方法。它比较简单,直接调用系统函数 killproc 来停止进程。如果研究一下killproc的代码,就会发现,其实就是将进程的可执行文件名和pid文件全路径(可选)传递进去,根据进程值来kill。


restart()

restart就没啥好多解释的了,先stop再start……

评论