DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

一、背景

项目过程中,经常会有很多的脚本,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

每分钟检测一次,没有启动则自动重启!通过这种方式来保证,脚本一定不死。

posted on   DoubleLi  阅读(534)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2021-10-27 FFmpeg libavutil主要功能概述
2020-10-27 编译程序遇到问题 relocation R_X86_64_32 against `.rodata' can not be used when making a shared object;
2017-10-27 mysql: not unique table/alias error. 如何解决
2014-10-27 directdraw显示yuv视频,出现屏保时,yuv显示不出来,表面丢失
2014-10-27 ddraw 视频下画图 不闪烁的方法
2011-10-27 js Tree - 树形菜单插件
点击右上角即可分享
微信分享提示