@xtccc
2015-09-21T13:44:56.000000Z
字数 3150
阅读 8869
Linux
之前写的应用,都是通过直接敲命令/写成script的形式在前台或者后台运行。如果能用 service {app-name} start/stop/status
的形式来启动app/停止app/查看运行状态,就更方便和简洁了。
实现一个custom service 需要自己写init script,这就离不开shell script的帮助,这里有一篇还不错的教程 —— Advanced Bash-Scripting Guide。
CentOS系统自带一个关于怎样写init script的文档,路径是 /usr/share/doc/initscripts-*/sysvinitfiles ,这里可以直接查看内容。
下面,通过一个简单的例子,来实现利用service {service-name} start
启动一个APP。
以下是Python写的APP,文件名为 /home/tao/xt-job.py
# -*- encoding: utf-8 -*-
import time
import sys
def main(args):
for i in range(0, len(args)):
print "args[" + str(i) + "] = ", args[i]
for i in range(0, 5):
print "hello ", i
time.sleep(1)
print "bye"
if __name__ == "__main__":
main(sys.argv)
现在,我们希望通过命令 service xt-service start
来运行这个app,那么,我们可以在目录 /etc/init.d 中创建一个名为 xt-service 的文件,其内容为:
#!/bin/bash
. /etc/init.d/functions
SERVICE_NAME="xiaotao-service"
RETVAL=0
start() {
echo -n "Starting $SERVICE_NAME: "
python -m /home/tao/xt-job 100 200 300
RETVAL=$?
}
case "$1" in
start)
start
;;
*)
echo "Now only `start` is available"
;;
esac
exit $RETVAL
好,现在我们试一试。
运行命令:
# service xt-service start
输出如下:
Starting xiaotao-service: args[0] = //home/tao/xt-job.py
args[1] = 100
args[2] = 200
args[3] = 300
hello 0
hello 1
hello 2
hello 3
hello 4
bye
预想的功能实现了!
在现实中,一个service需要实现的功能包含以下几个:
1. 令APP在后台运行,shell不输出;
2. 除了可以启动APP(start),还可以停止APP(stop),重启APP(restart),并可以查看其状态(status);
首先,我们把上面Python写成的APP改一改,让它每隔1秒往指定文件中输出一个数字,共输出50个数字,耗时50秒左右。
# -*- encoding: utf-8 -*-
# /home/tao/xt-daemon-job.py
import sys
import time
def main(args):
for i in range(0, len(args)):
print "args[" + str(i) + "] = ", args[i]
# 每隔1秒向文件中写入一个数字,共写入50个数字
with open(args[1], "w") as f:
for i in range(0, 500):
time.sleep(1)
f.write(str(i) + "\n")
if __name__ == "__main__":
main(sys.argv)
下面,创建名为 /etc/init.d/xt-daemon-service 的文件。
#!/bin/bash
. /etc/init.d/functions
SERVICE_NAME="xiaotao-daemon-service"
RETVAL=0
PID=-1
PIDFILE=/var/run/${SERVICE_NAME}.PID
start() {
# 首先检查PID文件是否已存在
if [ -f ${PIDFILE} ]; then
echo "PID file ${PIDFILE} already exists, please stop the service !"
exit
fi
echo "Starting service ${SERVICE_NAME} ..."
# >/dev/null 2>&1 表示不输出stdout和stderr
# 最后一个 & 表示整个命令在后台执行
cd "/home/tao/"
python -m xt-daemon-job A >/dev/null 2>&1 &
PID=$! # 获取本shell启动的最后一个后台程序的进程号(PID)
if [ -z ${PID} ]; then # 检查有没有获取到pid
echo "Failed to get the process id, exit!"
exit
else
echo "Starting successfully, whose pid is ${PID}"
fi
touch $PIDFILE
echo ${PID} > ${PIDFILE}
}
stop() {
if [ -f $PIDFILE ]; then # 检查PIDFILE是否存在
PID=`cat ${PIDFILE}`
if [ -z $PID ]; then # 检查PID是否存在于PIDFILE中
echo "PIDFILE $PIDFILE is empty !"
exit
fi
# 检查该进程是否存在
if [ -z "`ps axf | grep $PID | grep -v grep`" ]; then
echo "Process dead but pidfile exists!"
exit
else
kill -9 $PID
echo "Stopping service successfully , whose pid is $PID"
rm -f $PIDFILE
fi
else
echo "File $PIDFILE does NOT exist!"
fi
}
restart() {
stop
start
}
status() {
# 检查pid file是否存在
if [ -f $PIDFILE ]; then
PID=`cat $PIDFILE`
# 检查pid file是否存在pid
if [ -z $PID ] ; then
echo "No effective pid but pidfile exists!"
else
# 检查pid对应的进程是否还存在
if [ -z "`ps axf | grep $PID | grep -v grep`" ]; then
echo "Process dead but pidfile exist"
else
echo "Running"
fi
fi
else
echo "Service not running"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status
;;
*)
echo "Usage: xt-daemon-service {start|stop|restart|status}"
;;
esac
以上代码相当地self explainatory,下面还是简单地对要点做个总结:
- start app时,首先检查app是否正在运行。如果没有运行,则启动app,并创建一个pidfile,将app的pid写入pidfile中;
- stop app时,首先检查app是否正在运行。如果正在运行,则kill app并删除pidfile;
- 查看app status时,查找pidfile中的pid,并用 ps axf 命令来查看该pid对应的进程是否正在运行;