可能重复:
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版本的加分点。
答案 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 ...
您可以指定重试次数和等待时间。这是专为此目的而创建的,因此它可以处理竞争条件