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

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

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

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

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

流程图:

代码:

#! /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}

共享一个防止脚本重复启动的shell脚本的更多相关文章

  1. centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课

    centos   shell脚本编程1 正则  shell脚本结构  read命令  date命令的用法  shell中的逻辑判断  if 判断文件.目录属性  shell数组简单用法 $( ) 和$ ...

  2. 一个备份MySQL数据库的简单Shell脚本(转)

    Shell脚本是我们写不同类型命令的一种脚本,这些命令在这一个文件中就可以执行.我们也可以逐一敲入命令手动执行.如果我们要使用shell脚本就必须在一开始把这些命令写到一个文本文件中,以后就可以随意反 ...

  3. [转]一个备份MySQL数据库的简单Shell脚本

    本文翻译自 iSystemAdmin 的 <A Simple Shell Script to Backup MySQL Database> Shell脚本是我们写不同类型命令的一种脚本,这 ...

  4. spring boot 以jar的方式启动常用shell脚本

    用spring boot框架做的项目,将第三方包全部打在jar里面,通过shell脚本启动和停止服务,常用的shell脚本模板如下: #!/bin/bashJAVA_OPTIONS_INITIAL=- ...

  5. 一个自动安装LNMP的简洁Shell脚本

    此脚本在生产服务器上使用了一年多,本脚本崇尚简单唯美,只需要一个脚本就可以在任何一台有网络的服务器上自动配置LNMP.本脚本会在脚本执行目录下,建packages目录用于存放LNMP所需要的软件.大家 ...

  6. smbtar - 直接备份SMB/CIFS共享资源到UNIX磁带设备的shell脚本

    总览 smbtar -s server [-p password] [-x service] [-X] [-d directory] [-u user] [-t tape] [-b blocksize ...

  7. 做一个创建cocos2d-x新项目的shell脚本

    1. 进入console目录 cd /Users/apple/Documents/MyArchitecture/Cocos2d-x/Framework/cocos2d-x-3.4/tools/coco ...

  8. shell脚本实例,通向shell脚本大师的必经之路

    概述 读书百遍其义自见,shell脚本也是,只要例子看得多了,自然就知道怎么写了.这里主要整理了20几个例子,因为内容比较多,所以分了几次来做介绍了.下面的实例最好先自己思考怎么去实现,然后再看下实现 ...

  9. 面试笔试-脚本-1:使用shell脚本输出登录次数最多的用户

    原题目: 一个文本类型的文件,里面每行存放一个登陆者的IP(某些行是反复的),写一个shell脚本输出登陆次数最多的用户. 之前刚看到这个题目时,立即没有想到一行直接解决的办法,尽管知道能够先进行排序 ...

随机推荐

  1. python-查询员工信息表

    python查询员工信息表 基本要求: 用户可以模糊查询员工信息 显示匹配了多少条,匹配字符需要高亮显示 代码: #!/usr/env python #coding:utf-8 import time ...

  2. webpack 配置 (支持 React SCSS ES6 编译打包 和 模块热更新 / 生成SourceMap)

    1.首先是目录结构 |-node_modules/ #包文件 |-build/ #静态资源生成目录 |-src/ #开发目录 |-js/ |-index.js #入口文件 |-app.js #Reac ...

  3. CentOS6.6x86_64 部署 Nginx1.62+MySQL5.6.20+PHP5.6.4

    准备工作 切换到管理员身份 su - 安装编译扩展 yum install -y gcc-c++ 创建数据库目录.代码目录 mkdir /mnt/data /mnt/www 安装Nginx 1.6.2 ...

  4. Word复制和替换实例

    public string Path { get { DirectoryInfo info = new DirectoryInfo(Application.StartupPath); return i ...

  5. MIME协议

    转:http://blog.csdn.net/flfna/article/details/5048290 MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候 ...

  6. MSChart使用之双Y轴使用

    protected void SearchChart() { Chart1.ChartAreas.Clear(); Chart1.Series.Clear(); ChartArea _ChartAre ...

  7. MySQL 元数据

    MySQL 元数据 你可能想知道MySQL以下三种信息: 查询结果信息: SELECT, UPDATE 或 DELETE语句影响的记录数. 数据库和数据表的信息: 包含了数据库及数据表的结构信息. M ...

  8. Nginx配置文件nginx.conf详细说明

    Nginx配置文件nginx.conf详细说明 #worker_processes 8; #worker_cpu_affinity 00000001 00000010 00000100 0000100 ...

  9. 在fragment中获取他附着的activity中的变量

    final String data=(关联的activity类)getActivity().getData(); getData();自定义的方法

  10. CodeForces 546C(队列)

    CodeForces 546C Soldier and Cards Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I ...