共享一個防止腳本重復啟動的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}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM