@xtccc
2015-09-21T05:44:56.000000Z
字数 3150
阅读 9239
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 timeimport sysdef main(args):for i in range(0, len(args)):print "args[" + str(i) + "] = ", args[i]for i in range(0, 5):print "hello ", itime.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/functionsSERVICE_NAME="xiaotao-service"RETVAL=0start() {echo -n "Starting $SERVICE_NAME: "python -m /home/tao/xt-job 100 200 300RETVAL=$?}case "$1" instart)start;;*)echo "Now only `start` is available";;esacexit $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.pyimport sysimport timedef 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/functionsSERVICE_NAME="xiaotao-daemon-service"RETVAL=0PID=-1PIDFILE=/var/run/${SERVICE_NAME}.PIDstart() {# 首先检查PID文件是否已存在if [ -f ${PIDFILE} ]; thenecho "PID file ${PIDFILE} already exists, please stop the service !"exitfiecho "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 # 检查有没有获取到pidecho "Failed to get the process id, exit!"exitelseecho "Starting successfully, whose pid is ${PID}"fitouch $PIDFILEecho ${PID} > ${PIDFILE}}stop() {if [ -f $PIDFILE ]; then # 检查PIDFILE是否存在PID=`cat ${PIDFILE}`if [ -z $PID ]; then # 检查PID是否存在于PIDFILE中echo "PIDFILE $PIDFILE is empty !"exitfi# 检查该进程是否存在if [ -z "`ps axf | grep $PID | grep -v grep`" ]; thenecho "Process dead but pidfile exists!"exitelsekill -9 $PIDecho "Stopping service successfully , whose pid is $PID"rm -f $PIDFILEfielseecho "File $PIDFILE does NOT exist!"fi}restart() {stopstart}status() {# 检查pid file是否存在if [ -f $PIDFILE ]; thenPID=`cat $PIDFILE`# 检查pid file是否存在pidif [ -z $PID ] ; thenecho "No effective pid but pidfile exists!"else# 检查pid对应的进程是否还存在if [ -z "`ps axf | grep $PID | grep -v grep`" ]; thenecho "Process dead but pidfile exist"elseecho "Running"fifielseecho "Service not running"fi}case "$1" instart)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对应的进程是否正在运行;