检查脚本双重执行[重复]

Posted

技术标签:

【中文标题】检查脚本双重执行[重复]【英文标题】:Check script double execution [duplicate] 【发布时间】:2019-07-08 15:16:23 【问题描述】:

我有一个 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' 'ENDprint 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

通过这种方式,我检查了我的日志中有多少行,如果结果多于一个,那么我有两个正在执行的进程,一个将被停止。 但是,此方法无法正常工作。如何修复我的代码以检查我有多少正在执行的脚本?

【问题讨论】:

为什么不创建临时文件并处理,因为它是信号量? 什么是调度它? @chepner 我已经安排好了脚本开始的时间。每天在同一时间执行我的脚本 如果您正确配置了调度程序(cron 或任何您使用的),则不会发生这种情况。我建议您解决根本原因,而不是添加花里胡哨。 @AndrejsCainikovs 不幸的是,我不是管理调度程序的人,我无法对其进行操作。我唯一的选择是预测潜在的错误并修复它 【参考方案1】:

flock(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

这确保了“(”和“)”之间的代码一次只能由一个进程运行,并且该进程确实等待锁定的时间过长。

Credit goes to Alex B.

【讨论】:

【参考方案2】:

任何涉及:

    读取一些状态信息 检查结果 根据结果采取行动 完成

必须同时执行所有三个步骤,否则会出现“竞争”情况。例如:

(A) 读取状态 (A) 检查结果(正常) (A) 执行操作(ok) (A) 完成 (B) 读取状态 (B) 检查结果(差) (B) 采取行动(坏) (B) 完成

但如果时间稍有不同:

(A) 读取状态 (A) 检查结果 (ok) (B) 读取状态 (B) 检查结果(正常) (A) 执行操作 (ok) (B) 执行操作(ok) (A) 完成 (B) 完成

人们给出的常见示例是更新银行余额。

使用您的方法,您可能能够在不应该的情况下降低代码运行的频率,但您永远无法完全避免它。

更好的解决方案是使用锁定。这保证了一次只能运行一个进程。例如,使用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

【讨论】:

以上是关于检查脚本双重执行[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用双重逻辑非(!!)运算符感到困惑[重复]

检查Windows脚本中目录中的所有文件[重复]

我如何检查这些双重正则表达式

检查用户是不是存在[重复]

在c ++中捕获shell脚本退出状态[重复]

宝塔定时任务重复怎么办