我有一个bash脚本,有时甚至发生,即使我的脚本是预定的,它也执行了两次。因此,我添加了几行代码来检查脚本是否已在执行中。最初我没有问题,但是最近三天我又遇到了问题
PID=`echo $$`
PROCESS=${SL_ROOT_FOLDER}/xxx/xxx/xxx_xxx_$PID.txt
ps auxww | grep $scriptToVerify | grep -v $$ | grep -v grep > $PROCESS
num_proc=`awk -v RS='\n' 'END{print NR}' $PROCESS`
if [ $num_proc -gt 1 ];
then
sl_log "---------------------------Warning---------------------------"
sl_log "$scriptToVerify already executed"
sl_log "num proc $num_proc"
sl_log "--------"
sl_log $PROCESS
sl_log "--------"
exit 0;
fi
通过这种方式,我检查了日志中有多少行,如果结果多于一行,则我有两个正在执行的进程,一个将被停止。 但是,此方法无法正常工作。如何修复代码以检查执行中的脚本有多少?
答案 0 :(得分:1)
涉及到的一切:
必须同时执行所有三个步骤,否则会出现“竞赛”情况。例如:
但如果时间略有不同:
人们通常给出的示例是更新银行余额。
使用您的方法,可以减少不应执行的代码的运行频率,但您永远无法完全避免。
更好的解决方案是使用锁定。这样可以保证一次只能运行一个进程。例如,使用flock
,您可以将所有调用包装到脚本中:
flock -x /var/lock/myscript-lockfile myscript
或者,在脚本中,您可以执行以下操作:
exec 300>/var/lock/myscript-lockfile
flock -x 300
# rest of script
flock -u 300
或:
exec 300>/var/logk/myscript-lockfile
if ! flock -nx 300; then
# another process is running
exit 1
fi
# rest of script
flock -u 300
答案 1 :(得分:1)
#!/bin/bash
# Makes sure we exit if flock fails.
set -e
(
# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10 200
# Do stuff
) 200>/var/lock/.myscript.exclusivelock
这可确保“(”和“)”之间的代码一次仅由一个进程运行,并且该进程确实等待锁定的时间太长。