在以前的工作场所,我们曾经有一个高度精炼的bash函数叫做run-only-once,我们可以写入任何长时间运行的shell脚本,然后在脚本的开头调用它,这将检查是否脚本已作为另一个进程运行,如果是,则退出并向STDOUT发送通知.
有没有人有他们可以共享的功能/片段?
我们的旧函数(我不再拥有)会检查/ var/run中的PID文件(以scriptname.$$格式),然后使用exit或者只是继续.在存在PID文件的情况下,它会进行一些检查以确保该进程仍处于活动状态.它还有几个选项来控制是否输出通知.
从内存来看,我们的功能只适用于bash./ bin/sh版本的加分点.
Nei*_*lis 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}
Run Code Online (Sandbox Code Playgroud)
最后
if [ -f ${PIDFILE} ]; then
rm ${PIDFILE}
fi
Run Code Online (Sandbox Code Playgroud)
首先检查pid文件是否存在,如果存在则退出.如果是,则确认此脚本名称下的进程正在运行,如果是,则退出.如果没有,那么它继续并使用新的pid文件更新脚本.最后一位检查pid文件是否存在并删除它,因此脚本可以在下次运行.
检查/ var/run的权限对于您的脚本是否正常,否则在另一个目录中创建PID文件.与运行脚本相同的目录也没问题.
从shell执行原子锁有两种方法.最简单,最便携的是mkdir.如果已存在该名称的文件/目录,则创建目录将始终失败,因此只需使用"锁定目录"而不是"锁定文件".
mkdir "$LOCK" || { echo "Script already running" ; exit 1 ; }
Run Code Online (Sandbox Code Playgroud)
另一种方法是noclobber选项,使用设置set -C.此选项强制shell打开带有O_EXCL标志的输出重定向文件.像这样使用它:
set -C
> "$LOCK" || { echo "Script already running" ; exit 1 ; }
set +C
Run Code Online (Sandbox Code Playgroud)
您可能更愿意回显当前的PID或其他有用的内容以存储在文件中,而不是重定向空命令.
值得记住的是,一些古老的历史性外壳破坏了noclobber选项的实现,-C这些实现不使用O_EXCL,而是对文件存在进行错误的非原子检查.可能不是21世纪的问题,但你应该意识到以防万一.