PHP实现守护进程的启动和终止操作

PHP也是可以直接进行守护进程的启动与终止的,相对于shell来说会简单很多,理解更方便,当然了PHP守护进程要实现自动重启还是要依赖于shell的crontab日程表,每隔一段时间去执行一次脚本看脚本是否需要重启,如果需要则杀掉进程删除RunFile文件,重新启动并在RunFile文件中写入pid。

本文目录:

<?php       
function start($file){
    $path = dirname(__FILE__).'/';
    $runfile = $path.$file.'.run';
    $diefile = $path.$file.'.die';
    $file = $path."data/{$file}.php";
    clearstatcache();
    if(file_exists($runfile)){
        $oldpid = file_get_contents($runfile);
        $nowpid = shell_exec("ps aux | grep 'php -f process.php' | grep ${oldpid} | awk '{print $2}'");
        //如果runfile中的pid号可以匹配到正在运行的,并且上次访问runfile的时间和现在相差小于5min则返回
        if(($oldpid == $nowpid) && (time() - fileatime($runfile) < 300)){
            echo "$file is circle runing no";
            return;
        }else{
            //pid号不匹配或者已经有300秒没有运行循环语句,直接杀掉进程,重新启动
            $pid = file_get_contents($runfile);
            shell_exec("ps aux | grep 'php -f process.php' | grep {$pid} | xargs --if-no-run-empty kill");
        }
    }else{
        //将文件pid写入run文件
        if(!($newpid = getmypid()) || !file_put_contents($runfile,$newpid)){
            return;
        }
        while(true){
            //收到结束进程新号,结束进程,并删除相关文件
            if(file_exists($diefile) && unlink($runfile) && unlink($diefile)){
                return;
            }
            /*这里是守护进程要做的事*/
            file_put_contents($file,"I'm Runing Now".PHP_EOL,FILE_APPEND);
            /***********************/
            touch($runfile);
            sleep(5);
        }
    }
}
start("test");

1.几个显示函数
2.action函数
3.is_true和is_false函数
4.confirm函数
5.pid检测相关函数
  5.1
checkpid、__pids_var_run和__pids_pidof函数
  5.2
pidfileofproc和pidofproc函数
6.重头戏(一):daemon函数
7.重头戏(二):killproc函数
8.重头戏(三):status函数
9.几个重要函数的总结和使用说明
  9.1
pid相关
  9.2
daemon的使用
  9.3
killproc的使用
  9.4
status的使用
10.memcached服务启动脚本示例

PHP写守护进程时要注意几点:


1.首先就是函数clearstatcache()函数那里,查官方手册可以知道该函数是清除文件状态缓存的,当在一个脚本中多次检查同一个文件的缓存状态时如果不用该函数就会出错,受该函数影响的有:stat(),
lstat(), file_exists(), is_writable(),is_readable(),
is_executable(), is_file(), is_dir(), is_澳门新葡亰赌995577,link(),filectime(),
fileatime(), filemtime(), fileinode(), filegroup(),fileowner(),
filesize(), filetype(), fileperms().

/etc/rc.d/init.d/functions几乎被/etc/rc.d/init.d/下所有的Sysv服务启动脚本加载,也是学习shell脚本时一个非常不错的材料,在其中使用了不少技巧。

2.在多次运行该脚本时,会在运行前进行检测,上次执行循环的时间距离现在大于300s或者pid号不匹配都会重启该进程(时间在每次执行循环式都要更新touch)。

在该文件中提供了几个有用的函数:

3.自动重启也用到了crontab的日程表,将该文件添加入日程表:

  • daemon:启动一个服务程序。启动前还检查进程是否已在运行。
  • killproc:杀掉给定的服务进程。
  • status:检查给定进程的运行状态。
  • success:显示绿色的”OK”,表示成功。澳门新葡亰赌995577 1
  • failure:显示红色的”FAILED”,表示失败。澳门新葡亰赌995577 2
  • passed:显示绿色的”PASSED”,表示pass该任务。澳门新葡亰赌995577 3
  • warning:显示绿色的”warning”,表示警告。澳门新葡亰赌995577 4
  • action:根据进程退出状态码自行判断是执行success还是failure。
  • confirm:提示”(Y)es/(N)o/(C)ontinue? [Y]”并判断、传递输入的值。
  • is_true:”$1″的布尔值代表为真时,返回状态码0,否则返回1。包括t、y、yes和true,不区分大小写。
  • is_false:”$1″的布尔值代表为假时,返回状态码0。否则返回1。包括f、n、no和false,不区分大小写。
  • checkpid:检查/proc下是否有给定pid对应的目录。给定多个pid时,只要存在一个目录都返回状态码0。
  • __pids_var_run:检查pid是否存在,并保存到变量pid中,同时返回几种进程状态码。是functions中重要函数之一。
  • __pids_pidof:获取进程pid。
  • pidfileofproc:获取进程的pid。但只能获取/var/run下的pid文件中的值。
  • pidofproc:获取进程的pid。可获取任意给定pidfile或默认/var/run下pidfile中的值。
crontab -e
#打开日程表,inset模式
*/3 * * * * /usr/bin/php -f process.php
#每3分钟执行一次,放置进程挂掉

前三个是functions文件最重要的3个函数,还用到了一些额外的辅助函数,稍稍有点复杂。所以由简至繁,先介绍并展示后面几个函数,再回头解释前3个函数。

这样就基本ok了,要是有具体功能的话还需改动代码。

以下是/etc/init.d/functions文件的开头定义的语句。设置umask值,使得加载该文件的脚本所在shell的umask为22。导出路径变量。但说实话,这个导出的路径变量并不理想,因为要为非rpm包安装的程序设计服务启动脚本时,必须写全路径命令,例如/usr/local/mysql/bin/mysql。因此,可以考虑将/etc/init.d/functions中的语句注释掉。

umask 022

# Set up a default search path.
PATH="/sbin:/usr/sbin:/bin:/usr/bin"
export PATH

PS:本文分析的/etc/init.d/functions文件是CentOS
7上的,和CentOS 6有些许区别,但该有的目的和动作都有。

 

1.几个显示函数

包括echo_success、success、echo_failure、failure、echo_passed、passed、echo_warning和warning函数。这几个函数的定义方式和使用方法完全一样。

以下是echo_success和success函数的定义语句。

echo_success() {
  [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
  echo -n "["
  [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
  echo -n $"  OK  "
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo -n "]"
  echo -ne "r"
  return 0
}

success() {
  [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_success
  return 0
}

很简单,就是不换行带颜色输出”[ OK ]”字样。

[root@xuexi ~]# . /etc/init.d/functions

[root@xuexi ~]# success
[root@xuexi ~]#                                            [  OK  ]
[root@xuexi ~]# echo_success
[root@xuexi ~]#                                            [  OK  ]

同理,剩余的几个状态显示函数也一样。

[root@xuexi ~]# echo_failure
[root@xuexi ~]#                                            [FAILED]
[root@xuexi ~]# failure
[root@xuexi ~]#                                            [FAILED]

 

2.action函数

这个函数在写脚本时还比较有用,可以根据退出状态码自动判断是执行success还是执行failure函数。

action函数定义语句如下:

action() {
  local STRING rc

  STRING=$1
  echo -n "$STRING "
  shift
  "$@" && success $"$STRING" || failure $"$STRING"
  rc=$?
  echo
  return $rc
}

这个函数定义的很有技巧。先将第一个参数保存并踢掉,再执行后面的命令(“$@”表示执行后面的命令)。所以,当action函数只有一个参数时,action直接返回OK,状态码为0,当超过一个参数时,第一个参数先被打印,再执行从第二个参数开始的命令。

例如:

[root@xuexi ~]# action
                                                           [  OK  ]
[root@xuexi ~]# action 5
5                                                          [  OK  ]
[root@xuexi ~]# action sleeping sleep 3
sleeping                                                   [  OK  ]
[root@xuexi ~]# action "moving file" mv xxxxxx.sh aaaaa.sh
moving file mv: cannot stat ‘xxxxxx.sh’: No such file or directory
                                                           [FAILED]

所以,在脚本中使用action函数时,可以让命令执行成功与否的判断显得更”专业”。算是一个比较有趣的函数。

通常,该函数会结合/bin/true和/bin/false命令使用,它们无条件返回0或1状态码。

action $"MESSAGES: " /bin/true
action $"MESSAGES: " /bin/false

例如,mysqld启动脚本中,判断mysqld已在运行时,直接输出启动ok的消息。(但实际上根本没做任何事)

if [ $MYSQLDRUNNING = 1 ] && [ $? = 0 ]; then
    # already running, do nothing
    action $"Starting $prog: " /bin/true
    ret=0

 

3.is_true和is_false函数

这两个函数的作用是转换输入的布尔值为状态码。

is_true() {
    case "$1" in
    [tT] | [yY] | [yY][eE][sS] | [tT][rR][uU][eE])
    return 0
    ;;
    esac
    return 1
}

is_false() {
    case "$1" in
    [fF] | [nN] | [nN][oO] | [fF][aA][lL][sS][eE])
    return 0
    ;;
    esac
    return 1
}

当is_true函数的第一个参数(后面的参数会忽略掉)为忽略大小写的t、y、yes或true时,返回状态码0,否则返回1。
当is_false函数的第一个参数(后面的参数会忽略掉)为忽略大小写的f、n、no或false时,返回状态码0,否则返回1。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图