【shell】防止脚本重复运行

有些业务脚本需要防止重复,以便造成业务数据不一致。

所以,一般在脚本运行开始,就首先要检查当前系统是否有该脚本的运行进程。

一般人多半是这样写的(比如我们系统里的那帮人):

processName="OMIGet_HOUR.sh"
processNum=`ps -aef |grep "${processName}" | wc -l`

if [ "${processNum}" -gt "3" ]; then
  echo "已经有脚本在运行,本脚本不支持多实例运行${processNum}"
  exit 1
fi

这样写有个问题,是什么呢?

ps -ef  | grep 的返回结果在是否包含grep时具有不确定性(可以加上-v参数避免,但很麻烦)。所以稍不注意,判断就会失败。

其实我们可以使用更安全的一种方式来判断,如:

#!/bin/ksh

RUNDIR=`dirname $0`
PIDFILE="${RUNDIR}/$0.pid"

if [ -s ${PIDFILE} ]; then
  echo "脚本已经在运行,不重复运行,退出."
  exit 1
fi
echo $$ > ${PIDFILE}

<各种业务处理逻辑>

cat /dev/null > ${PIDFILE}
借助pidfile来判断,脚本在运行之初判断是否有进程号即可。

当然,如果脚本在运行之中被强制kill掉,那么下次怎么也运行不起来了。

不过这个问题,我们可以这样来解决:在脚本“假退出”之前,通过各种告警来提示维护人员(以手工介入处理)。


网上有很多关于在shell执行文件本身通过flock的命令加锁来实现互斥的方式,个人觉得,该方法不具有自助可控性,风险较大,最重要的是不具有平台通用性。

所以更加推荐如下方式:

#!/bin/ksh

RUNDIR=`dirname $0`
PIDFILE="${RUNDIR}/$0.pid"

if [ -s ${PIDFILE} ]; then
   SPID=`cat ${PIDFILE}`
   if [ -e /proc/${SPID}/status ]; then
      echo "脚本已经在运行,不重复运行,退出."
      exit 1
  fi
  cat /dev/null > ${PIDFILE}
fi
echo $$ > ${PIDFILE}

#各种业务逻辑

cat /dev/null > ${PIDFILE}

经过测试,该方法能够表现良好。

你可能感兴趣的:(Linux系统)