如何给脚本写一个守护进程

 我来答
春城闭海b0
2016-12-30 · TA获得超过223个赞
知道答主
回答量:164
采纳率:0%
帮助的人:72.9万
展开全部
在我们日常运维中,写脚本监控一个进程是比较常见的操作,比如我要监控mysql进程是否消失,如果消失就重启mysql,用下面这段代码就可以实现:

#!/bin/sh

Date=` date '+%c'`

while :
do
if ! psaux | grep -w mysqld | grep -v grep >/dev/null 2>&1
then
/etc/init.d/mysqldstart
echo $Datemysqldwasreboot >>/var/log/reboot_mysql.log
fi
done

本篇这是以mysql为例子,但实际中如果是监控的脚本出了问题,报警没发出来,那就比较尴尬了,所以为保证我们的检查脚本能实时运行,我们需要一个进程来守护这个脚本,这就是我们今天要说的主题,如何给脚本写一个daemon,我们先上代码:

#!/usr/bin/python

import subprocess
from daemonimport runner

cmd = "/root/demo_script/restart_mysql.sh"

class App():
def __init__(self):
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/tmp/hello.pid'
self.pidfile_timeout = 5
def start_subprocess(self):
return subprocess.Popen(cmd, shell=True)
def run(self):
p = self.start_subprocess()
while True:
res = p.poll()
if resis not None:
p = self.start_subprocess()

if __name__ == '__main__':
app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()

脚本比较简单,没什么特别的逻辑,关于daemon这个模块如何使用,我这里给出官方的解释,注意哟,是英文的,我就不翻译了,如果有生词就查查字典,就当多学几个了单词吧。

__init__(self, app)
| Setuptheparametersof a new runner.
|
| The `app` argumentmusthavethefollowingattributes:
|
| * `stdin_path`, `stdout_path`, `stderr_path`: Filesystem
| pathsto openand replacetheexisting `sys.stdin`,
| `sys.stdout`, `sys.stderr`.
|
| * `pidfile_path`: Absolutefilesystempathto a filethat
| willbeusedas thePIDfilefor thedaemon. If
| ``None``, noPIDfilewillbeused.
|
| * `pidfile_timeout`: Usedas thedefault acquisition
| timeoutvaluesuppliedto therunner's PIDlockfile.
|
| * `run`: Callablethatwillbeinvokedwhenthedaemonis
| started.
|
| do_action(self)
| Performtherequestedaction.
|
| parse_args(self, argv=None)
| Parsecommand-linearguments.

这样就完成了,守护进程的启动比较高大上,输入以上代码后,可以直接在终端输入:

#python monitor.py start

当然还有stop,restart等参数。

这里我介绍的是其中一个应用场景,实际中可以灵活运用,比如1台服务器上启动的程序过多,环境配置比较复杂,就可以先启动daemon进程,然后通过daemon来启动其它所有应用程序,就不用一个一个应用程序启动了,这篇就到这里,有问题可以给我留言。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
llzzcc66
2016-12-30 · 知道合伙人数码行家
llzzcc66
知道合伙人数码行家
采纳数:81385 获赞数:171496
公司运维员工

向TA提问 私信TA
展开全部
一、背景
项目过程中,经常会有很多的脚本,Shell脚本、PHP脚本、Python脚本等,更有一些脚本是需要常驻内存执行的,简而言之就是需要while(true){}的模式执行。
但是有的时候,一个常驻内存的进程会因为某些耗时操作而夯住,不再往下继续执行,成为了一个僵尸进程;或者因为某个操作偶然出错,直接退出了;所以我们需要有一套简单的机制来保证进程一直处于活跃状态。
二、方案
以一个PHP脚本为例:
脚本中依然采用while(true){}方式,但是额外增加一个执行时间的控制,即,设定当前脚本执行超过某个时间之后,自动退出
脚本自动退出之后,通过一个守护进程自动重启
三、实现
1、PHP脚本范例
脚本名称:script/monitor/Collect.class.php
class Collect extends \Framework\FrameworkScript {

// 表示:脚本最多能活跃10分钟
private $interval = 600;

// 脚本入口
public function run() {

$start = time();
while (true) {
// here , do what you want to do...

// 如果数据为空,则10分钟自杀进程
if (time() - $start > $this->interval) {
exit(0);
}
}
}
}

2、守护进程范例
守护进程脚本名称:script/monitor/Watch.sh
#!/bin/bash
# @author xianliezhao

# crontab命令:
# 监控线上服务稳定性情况
# */1 * * * * sh /home/work/script/monitor/Watch.sh start >> /home/work/logs/script_monitor_watch.log

# PHP命令
php="/home/service/php/bin/php /home/work/mlservice/goods/public/script.php"

# 在这里配置所有需要【守护】的PHP进程
proc_list='monitor\\Collect monitor\\RealtimeAnalytics'

#work 账户运行
name=$(whoami)
if [ $name != 'work' ];then
echo `date "+%Y/%m/%d %H:%M:%S> "` "必须用work账户"
exit
fi

#开启服务
start() {
for proc in $proc_list ;do
arrm=$(ps -ef | grep "`echo $proc`" | grep -v 'grep' | awk -F'script.php' '{print $2}'| wc -l)
if [ ${arrm:-0} = 0 ];then
$php $(echo $proc | awk -F"\\" '{print $1"\\"$3}') >/dev/null &
echo `date "+%Y/%m/%d %H:%M:%S> "` "$proc 进程已经重启"
else
echo `date "+%Y/%m/%d %H:%M:%S> "` "$proc 进程已经存在"
fi
done
}

#停止服务
stop() {
for proc in $proc_list ;do
arrproc=$(ps -ef | grep "`echo $proc`" | awk '{print $2}')
for p in $arrproc; do
kill $p;
echo `date "+%Y/%m/%d %H:%M:%S> "` $p " 进程已杀死!"
done
done
echo `date "+%Y/%m/%d %H:%M:%S> "` "服务已停止!"
}

#check脚本是否运行
check() {
for proc in $proc_list ;do
arrspar=$(ps -ef | grep "`echo $proc`" | grep -v 'grep' | awk '{print $2}')
echo `date "+%Y/%m/%d %H:%M:%S> "` "目前运行的服务监控进程($proc):" ${arrspar:-"无"}
done
}

usage() {
cat <<EOF
守护进程使用方法(需要 work 用户执行):

usage: sh $0 check|start|stop|restart
start 启动服务
stop 停止服务
check 检查服务是否正常
EOF
exit
}

while true;do
case $1 in
start)
start
break
;;
help)
usage
break
;;
stop)
stop
break
;;
check)
check
break
;;
*)
usage
break
;;
esac
shift
done

四、使用
1、使用帮助
[work@script-01 monitor]$ sh Watch.sh
守护进程使用方法(需要 work 用户执行):

usage: sh Watch.sh check|start|stop|restart
start 启动服务
stop 停止服务
check 检查服务是否正常

2、检测脚本执行状态
[work@script-01 monitor]$ sh Watch.sh check
2015/09/24 15:10:48> 目前运行的服务监控进程(monitor\\Collect): 65321
2015/09/24 15:10:48> 目前运行的服务监控进程(monitor\\RealtimeAnalytics): 无

3、通过守护进程手动重启脚本
[work@script-01 monitor]$ sh Watch.sh start
2015/09/24 15:11:26> monitor\\Collect 进程已经重启
2015/09/24 15:11:26> monitor\\RealtimeAnalytics 进程已经重启

4、通过crontab自动守护
# crontab命令:
# 监控线上服务稳定性情况
*/1 * * * * sh /home/work/script/monitor/Watch.sh start >> /home/work/logs/script_monitor_watch.log

每分钟检测一次,没有启动则自动重启!通过这种方式来保证,脚本一定不死。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式