Shell Programming(二)——编写守护进程脚本

概述

在Linux开发中,常遇到需要编写守护进程程序的场景,这时候视情况而定,能使用Shell Script编写那自然就方便很多了。这里就来编写一个守护进程脚本,以作参考。

获取需要守护的进程pid

获取进程信息常用ps指令进行查询,比较常用的是-ef选项,获取所有进程信息则可以这样写:

ps -ef

有了上面这步,我们可以得到大量的进程信息,此时就需要使用上一篇blog中提到的管道结合grep进行文本查找了,这里需要注意,我们需要先过滤掉grep相关的进程信息,因为在这里使用了grep,使用-v选项则可以过滤相关信息,合起来就可以这样写:

ps -ef | grep -v "grep" | grep program.sh  # 查找所需进程相关信息

到了这里,已经完成了大半了,我们可以将上面的shell放到Terminal里试试,可以看到,结果并不是pid,而是完整的该进程信息,我们需要截取其中的pid。这里就可以使用awk来进行截取了,awk将输入的文本,默认以空格为分隔符,分割出多个部分,ps使用-ef选项后,pid在第二个位置,所以最后的shell可以这样写:

ps -ef | grep -v "grep" | grep program.sh | awk '{print $2}'  # 获取进程pid

编写守护进程脚本

有了上面的知识,就可以简单写一个守护进程脚本了。

#!/bin/bash 

    export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:./ 

    pid="" 
    while true; do 
        pid="`ps gaux | grep -v "grep" | grep \"program.sh\" | awk '{print $2}'`" 
        if [ "${pid}" == "" ]; then 
            echo "program is halt."  # 仅是示意,主要的功能可以写在这里 
        fi 
    done

缺陷

上述的脚本是以死循环形式,一直运行检测程序运行状态的,但其实对于大多数程序来说,挂掉的时间相对于总的运行时间来说,是非常小的,所以这样的守护进程脚本一直在运行,其实也会浪费一些系统资源。考虑一下,其实守护进程的情况,在分钟级能够重启,对于多数情况也是够用的,所以这里也可以考虑使用crontab来实现,crontab的最小单位也是分钟级。

如此,上述的shell script也就可以改成这样:

#!/bin/bash 

    export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:./ 

    pid="" 
    pid="`ps gaux | grep -v "grep" | grep \"program.sh\" | awk '{print $2}'`" 
    if [ "${pid}" == "" ]; then 
        echo "program is halt."  # 仅是示意,主要的功能可以写在这里 
    fi

crontab配置文件,每个配置项是以”* * * * *”来标识时间的,分别代表分、时、日(几号)、月、星期几,所以简单使用的话,则可以这样写:

*/1 * * * * your_guard_prog

通过crontab来实现守护进程的作用后,虽然每分钟也会执行一次,但是相对于死循环一直执行,cpu时间的占用是要少一些的,节省了计算资源。
如果程序对于重启有很高的实时需求,crontab确实也没办法满足,这时候可以考虑下实现一个精度更高的定时任务程序,上面最简陋的守护脚本只是一个很不好的示范,参考下就好了。