Shell片段确保在任何给定时间只运行一个shell脚本实例

时间:2009-06-06 11:06:48

标签: shell

  

可能重复:
  Quick-and-dirty way to ensure only one instance of a shell script is running at a time

在以前的工作场所,我们曾经有一个高度精炼的bash函数,称为只运行一次,我们可以写入任何长时间运行的shell脚本,然后在脚本的开头调用它,这将检查查看脚本是否已作为另一个进程运行,如果是,则退出并通知STDOUT。

有没有人有他们可以共享的功能/片段?

我们的旧函数(我不再拥有)将检查/ var / run中的PID文件(以scriptname。$$格式),然后使用exit或者只是继续。在存在PID文件的情况下,它会进行一些检查以确保该进程仍处于活动状态。它还有几个选项来控制是否输出通知。

从内存来看,我们的功能只适用于bash。 / bin / sh版本的加分点。

3 个答案:

答案 0 :(得分:10)

将其放在脚本的开头

SCRIPTNAME=`basename $0`
PIDFILE=/var/run/${SCRIPTNAME}.pid


if [ -f ${PIDFILE} ]; then
   #verify if the process is actually still running under this pid
   OLDPID=`cat ${PIDFILE}`
   RESULT=`ps -ef | grep ${OLDPID} | grep ${SCRIPTNAME}`  

   if [ -n "${RESULT}" ]; then
     echo "Script already running! Exiting"
     exit 255
   fi

fi


#grab pid of this process and update the pid file with it
PID=`ps -ef | grep ${SCRIPTNAME} | head -n1 |  awk ' {print $2;} '`
echo ${PID} > ${PIDFILE}

并在最后

if [ -f ${PIDFILE} ]; then
    rm ${PIDFILE}
fi

首先检查pid文件是否存在,如果存在则退出。如果是,则确认此脚本名称下的进程正在运行,如果是,则退出。如果没有,那么它继续并使用新的pid文件更新脚本。最后一位检查pid文件是否存在并删除它,因此脚本可以在下次运行。

检查/ var / run的权限对于您的脚本是否正常,否则在另一个目录中创建PID文件。与运行脚本相同的目录就可以了。

答案 1 :(得分:5)

有两种方法可以从shell执行原子锁。最简单,最便携的是mkdir。如果已存在该名称的文件/目录,则总是的目录创建将失败,因此只需使用“锁定目录”而不是“锁定文件”。

mkdir "$LOCK" || { echo "Script already running" ; exit 1 ; }

另一种方法是使用set -C设置的noclobber选项。此选项强制shell使用O_EXCL标志打开文件以进行输出重定向。像这样使用它:

set -C
> "$LOCK" || { echo "Script already running" ; exit 1 ; }
set +C

您可能更喜欢回显当前的PID或其他有用的内容以存储在文件中,而不是重定向空命令。

值得注意的是,一些古老的历史性shell已经破坏了noclobber选项-C的实现,它们不使用O_EXCL,而是对文件存在进行非原子检查。可能不是21世纪的问题,但你应该意识到以防万一。

答案 2 :(得分:1)

在Linux中使用lockfile实用程序更可靠。

从手册页:

         ...
         lockfile important.lock
         ...
         access_"important"_to_your_hearts_content
         ...
         rm -f important.lock
         ...

您可以指定重试次数和等待时间。这是专为此目的而创建的,因此它可以处理竞争条件