需求:
我们需要使用linux的crontab实现每分钟执行一下shell脚本,shell脚本有时的执行时间会超过1分钟,要求上次执行的shell脚本还在运行,放弃此次执行.
分析:
假如我们的shell脚本叫test.sh
*/1 * * * * /home/zhangsan/test.sh >> /home/zhangsan/run.log 2>&1
这个命令表面看齐来没什么问题,但是如果遇到脚本执行超过1分钟的情况, 脚本还没有执行,又到了crontab下次执行的时间了,那么crontab又会执行一下脚本,如果我们shell脚本里没有一些判断,此时后台就会有两个test.sh 同时运行.
解决:
方法一:用一个文件来当锁
readonly LOCK_FILE="/tmp/$(basename $0 .sh).lock" #获取锁 function get_lock(){ if [[ -e ${LOCK_FILE} ]] ; then echo "脚本正在运行!" exit 1 fi #设置锁 touch ${LOCK_FILE} #自动释放锁 trap "rm -rf ${LOCK_FILE}" 0 1 2 3 8 9 14 15 }
这只是一个简单的例子,没一运行脚本之前可以执行下get_lock方法来获取锁判断脚本是否正在执行.
这种方法虽然比较简单,但是这段代码对我们功能本身完全是无用的.
方法二: 借助flock命令
语法:
flock [options] <file>|<directory> <command> [<argument>...] flock [options] <file>|<directory> -c <command> flock [options] <file descriptor number>
参数:
-s, --shared: 获得一个共享锁 -x, --exclusive: 获得一个独占锁(不加参数默认) -u, --unlock: 移除一个锁,通常是不需要的,脚本执行完会自动丢弃锁 -n, --nonblock: 如果没有立即获得锁,直接失败而不是等待 -w, --timeout: 如果没有立即获得锁,等待指定时间 -E, --conflict-exit-code <number> exit code after conflict or timeout -o, --close: 在运行命令前关闭文件的描述符号。用于如果命令产生子进程时会不受锁的管控 -c, --command: 在shell中运行一个单独的命令 -h, --help 显示帮助 -V, --version: 显示版本
借助flock命令,我们只需要把crontab的执行命令改成
*/1 * * * * flock -xn /tmp/mytest.lock "sh /home/zhangsan/test.sh >> /home/zhangsan/run.log 2>&1 "
这样每次到时执行时,flock都会先获取锁,获取到了执行shell脚本,没有获取到直接退出.
那么借助flock命令,方法一的脚本的另一种写法:
readonly LOCK_FILE="/tmp/$(basename $0 .sh).lock" exec 200>$LOCK_FILE flock -n 200 || { echo "脚本正在运行!" exit 1 }
不需要我们手动释放锁,脚本执行完会自动释放
还没有评论,来说两句吧...