Shell脚本:确保在已经运行的情况下不执行脚本

Ind*_*ial 12 bash shell cron

可能重复:
确保一次只运行一个shell脚本实例的快速和脏方法

我已经设置了一个cronjob来正确备份我的文件夹,我很自豪.但是,我通过查看备份的结果发现,我的备份脚本已被Crontab多次调用,导致同时运行多个备份.

有没有什么办法可以确保某个shell脚本在同一个脚本已经执行时不能运行?

Arn*_*anc 33

没有竞争条件或提前退出问题的解决方案是使用锁定文件.该flock实用程序处理得非常好,可以像这样使用:

flock -n /var/run/your.lockfile -c /your/script
Run Code Online (Sandbox Code Playgroud)

如果脚本已在运行,它将立即返回非0状态.


pax*_*blo 7

通常和简单的方法是这样做:

if [[ -f /tmp/myscript.running ]] ; then
    exit
fi
touch /tmp/myscript.running
Run Code Online (Sandbox Code Playgroud)

在你的脚本和

rm -f /tmp/myscript.running
Run Code Online (Sandbox Code Playgroud)

最后,以及在trap功能未达到目的的情况下.

这仍然有一些潜在的问题(例如顶部的竞争条件),但绝大多数情况都会这样.

  • 由于在"文件不存在"和"创建文件"之间的TOCTOU(检查时间,使用时间)存在竞争条件.原子机制是`mkdir /tmp/myscript.running 2>/dev/null`.如果目录存在,`mkdir`将失败,并且内核确保只有一个并发运行的`mkdir`命令(系统调用)成功. (9认同)

小智 5

没有锁文件的好方法:

ps | grep $0 | grep -v grep > /var/tmp/$0.pid
pids=$(cat /var/tmp/$0.pid | cut -d ' ' -f 1)
for pid in $pids
do
   if [ $pid -ne $$ ]; then
      logprint " $0 is already running. Exiting"
      exit 7
   fi
done
rm -f /var/tmp/$0.pid
Run Code Online (Sandbox Code Playgroud)

这样做没有锁定文件,这很酷.ps进入临时文件,刮掉第一个字段(pid#)并寻找自己.如果我们找到一个不同的,那么有人已经在运行.grep $ 0是将列表缩短到这个程序的那些实例,而grep -v grep摆脱了grep本身的行:)