之前做项目老大要求用写一服务,要求开机自启动,故研究了下shell脚本写服务的一些方法,感觉还是很不错的,写下来为了防止遗忘,码农不好干啊,记性越来越差了。
首先写一个小程序,模拟常驻进程,简单起见,也就不写什么精灵进程了,就为了实验下。
-
#include <stdio.h>
-
#include <unistd.h>
-
-
int main(int argc, char *argv[])
-
{
-
while (1)
-
{
-
sleep(10);
-
printf("hello, world\n");
-
}
-
return 0;
-
}
然后写一个shell脚本作为来启动这个进程,可以随系统开机自启动,关机时结束运行,这里以CenotOS为例,Ubuntu好像有点不同。一般linux的服务都可以查看进程运行状态,开始运行和结束运行,重新启动。所以实现这三个函数就OK了。得说明下,按照约定,一般服务的名字都以d结尾。为了使用系统提供给我们的一些函数,可以包含/etc/init.d/functions这个文件,它给我们提供的有:检查进程运行状态,得到进程ID,结束进程等一些常用的函数。这个脚本一时半会还不容易看懂,有时间再研究下。
首先是start函数,新建一个helld的文件,开头的固定格式为:
-
# chkconfig: 2345 99 97
-
-
if [ -f /etc/init.d/functions ] ; then
-
. /etc/init.d/functions
-
elif [ -f /etc/init.d/functions ] ; then
-
. /etc/init.d/functions
-
else
-
exit 1
-
fi
其中
# chkconfig: 2345 99 97中,2345代表该服务的运行级别(%E8%BF%90%E8%A1%8C%E7%BA%A7%E5%88%AB),99和97代表卡机时启动的优先级和停止服务时的优先级,也就是启动顺序和停止顺序,数值从0-99,越大的优先级越低。
-
$SERVICE_DIR="."
-
$PROC_NAME="hello"
-
start()
-
{
-
for process in $PROC_NAME
-
do
-
if process_running $process
-
then
-
echo "$process is already running, exiting..."
-
echo_failure
-
exit_code=1
-
else
-
nohup $SERVICE_DIR/$process > /dev/null 2>&1 &
-
echo_success
-
echo
-
fi
-
-
done
-
}
其中的process_running如下:
-
process_running()
-
{
-
self_pid=$(pidofproc $1)
-
if [ -n "$self_pid" ] ; then
-
return 0
-
else
-
return 1
-
fi
-
}
这个process_running是检测进程是否存在,只允许运行一个实例的一种做法,其实是有很多中做法的。像用C/C++写的程序,可以直接运行的这种,这个process_running可能已经足够了。但是如果是像python这一类需要解释器来运行的程序就不行了,具体的做法是可以使用pidfile或者自己另写一个足以检测进程存在,在/etc/init.d/fuctions里面的status函数里有讲怎么用pidfile。
然后是stop函数:
-
stop()
-
{
-
for process in $PROC_NAME
-
do
-
killproc $process
-
echo
-
RETVAL=$?
-
return $RETVAL
-
done
-
-
}
这其中用到了killproc这个函数,也是在/etc/init.d/functions里面实现的,具体的代码可以去参考下。
最后是判断状态的函数,重起个名,叫process_status,避免冲突了
-
process_status()
-
{
-
for process in $PROC_NAME
-
do
-
if ! status $process
-
then
-
exit_code=1
-
else
-
echo_failure
-
exit_code=0
-
fi
-
done
-
}
这样呢,就把一个服务可能用到的都写出来了,接下来就是调用这些函数,
-
case "$1" in
-
start)
-
start
-
;;
-
stop)
-
stop;;
-
restart|reload)
-
stop
-
sleep 1
-
start
-
;;
-
status)
-
process_status
-
;;
-
*)
-
echo $"Usate: $0 {start|stop|restart|status}"
-
exit_code=1
-
;;
-
esac
-
-
exit $exit_code
注意到在最后有一句exit $exit_code,主要是为了向它的父进程传递退出代码,即$?。写完了这些呢,我们还需要让它实现开机启动,依次以root用户执行命令:
-
mv hellod /etc/init.d
-
/sbin/chkconfig --add hellod #通过chkconfig添加一个新的服务
-
/sbin/chkconfig hellod on #将这个服务加入开机自启动
总算是大功告成了,很有成就感有木有,在满满的喜悦之后,俺也在感慨,现在写的这些简单的东西,实际上用到了其他人已经实现了的接口,真的是很感谢那些为linux付出的人。这么点东西一小会说完了,要用文字表达出来还是费了不少时间,惭愧啊。
阅读(4073) | 评论(2) | 转发(2) |