• 共享一个防止脚本重复启动的shell脚本


    项目的一个需求:为防止脚本重复调度,导致同时运行时相互冲突,需要在脚本运行开始前创建一个文件,结束时删除。

    脚本启动时判断一下文件是否存在,如果存在则退出。

    最开始这样做没发现问题,但跑一段时间后,发现如果进程中间退出没删除文件就会出现问题。

    而且有时希望等待一段时间后不管有没有已启动同名脚本,都往下走。

    基于以上考虑,最近将这个防止重复启动的逻辑抽离出来成为独立脚本,并增加了一些控制逻辑,这样以后需要类似功能直接调用这个脚本就好。

    流程图:

    代码:

    #! /bin/sh
    # singleton.sh 进程名($0) 进程id($$) 工作目录 休眠时间 尝试次数
    # 尝试次数为0代表无限次
    # 本脚本的作用是防止进程重复启动(类似单例) 脚本启动后会在工作目录生成一个进程信息文件(pidfile)起到唯一锁作用
    # 如果pidfile里面的进程不存在 脚本就会结束 否则会一直等待直到尝试次数超限
    
    if [ $# != 5 ]
    then
        echo "usage:singleton.sh 进程名($0) 进程id($$) 工作目录 休眠时间 尝试次数(0代表无限次)"
        exit 1
    fi
    
    v_proc_name=${1##*/}
    v_pid=$2
    v_work_dir=$3
    v_sleep_seconds=$4
    v_retry_times=$5
    # pid文件路径 模拟文件锁用的
    v_pid_file=${v_work_dir}/singleton_run_pid
    
    echo "cmd = $0 $*"
    
    # 判断pid文件是否存在
    # 如存在判断文件里面的进程是否存在 且进程名字相同
    # 如果符合以上条件则休眠后再次尝试 直至满足最大尝试次数
    if [ -f ${v_pid_file} ]
    then
        echo "file[${v_pid_file}] exists!"
        
        v_times=0
        v_max_retry_times=${v_retry_times}
        while [ ${v_times} -lt ${v_max_retry_times} -o ${v_retry_times} -eq 0 ]
        do
            v_pid_old="";v_proc_name_old="";
            read v_pid_old v_proc_name_old < ${v_pid_file}
            
            if [ "${v_pid_old}" = "" -o "${v_proc_name_old}" = "" ]
            then
                echo "error pidfile [$(cat ${v_pid_file})]"
                break;
            fi
            
            # 考虑到脚本有时被强制杀掉会导致pid文件残留没清理,这里加上对pid文件内容判断
            if [ ${v_proc_name_old} != ${v_proc_name} ]
            then
                echo "proc_name not euqal; [${v_proc_name_old}] != [${v_proc_name}]! do next;"
                break;
            fi
            
            if [ ${v_pid} = ${v_pid_old} ]
            then
                echo "pid euqal; [${v_pid}] = [${v_pid_old}]! do next;"
                break;
            fi
            
            # grep 参数 -- 代表参数结果 后面跟的是关键字或文件名 这是为了避免进程名是-bash的问题  
            v_pid_inf=$(ps -ef|awk -v v_pid_old=${v_pid_old} '{ if($2 == v_pid_old) print $0; }'|grep -w -- ${v_proc_name})
            if [ "${v_pid_inf}" = "" ]
            then
                echo "cannot find the pid[ps -ef|awk -v v_pid_old=${v_pid_old} '{ if($2 == v_pid_old) print $0; }'|grep -w -- ${v_proc_name}]! do next;"
                break;
            fi
            
            v_times=$(expr ${v_times} + 1)
            echo "try times ${v_times}; sleep ${v_sleep_seconds}"
            sleep ${v_sleep_seconds}
        done
        
        echo "had tried ${v_times} times! do next;"
    fi
    
    echo "create file[${v_pid_file}]!"
    echo ${v_pid} ${v_proc_name} > ${v_pid_file}
  • 相关阅读:
    RabbitMQ安装
    基于Linux的校园网破解思路和方法
    网络-0001-常见传输介质
    友情链接
    linux简史
    计算机的发展简史
    ArrayList&LinkedList&Vector区别
    Adobe Flash Player PPAPI 32.0.0.330
    ntoskrnl.exe导致蓝屏解决方法
    Git常用命令
  • 原文地址:https://www.cnblogs.com/kingstarer/p/6011499.html
Copyright © 2020-2023  润新知