使用flock命令确保脚本单例执行

来源:互联网 发布:贵州广电网络高清收费 编辑:程序博客网 时间:2024/06/01 08:41

使用flock命令确保脚本单例执行

 

问题的背景:

       我们常常需要通过crontab部署某个脚本运行某些定时任务,但在实际的过程中,一旦处理不好可能导致在同一时刻出现脚本的多个运行副本,比如crontab的调度是每5 分钟运行一次脚本,如果运行的脚本能够在5分钟内处理完任务并退出,则没问题,同一时刻最多只有一个脚本在运行,但如果脚本如果无法在5分钟内处理完任务并退出,则意味着在下一个5分钟,脚本又会被crontab调起来,出现了同一时刻有2个甚至更多的脚本事例在运行,对应一些依赖关系,需要串行处理的脚本来说,可能会导致数据相互覆盖等问题。

 

   为了解决这个问题,脚本必须能够自我保护,即在启动之前判断是否已经有脚本启动了,若当前已经有脚本启动了,则虽然crontab调度到该脚本,但脚本自身会马上退出。

   解决问题的思路很多,其中一种笔者觉得比较简便的是:使用文件锁,在linux中,提供了flock命令,具体格式如下:

1,  flock [-sxon] [-w timeout] lockfile [-c]command...

2,  flock [-sxun] [-w timeout] fd

 

参数说明如下:

-s为共享锁,在定向为某文件的FD上设置共享锁而未释放锁的时间内,其他进程试图在定向为此文件的FD上设置独占锁的请求失败,而其他进程试图在定向为此文件的FD上设置共享锁的请求会成功。

-e为独占或排他锁,在定向为某文件的FD上设置独占锁而未释放锁的时间内,其他进程试图在定向为此文件的FD上设置共享锁或独占锁都会失败。只要未设置-s参数,此参数默认被设置。

-u手动解锁,一般情况不必须,当FD关闭时,系统会自动解锁,此参数用于脚本命令一部分需要异步执行,一部分可以同步执行的情况。

-n为非阻塞模式,当试图设置锁失败,采用非阻塞模式,直接返回1,并继续执行下面语句。

-w设置阻塞超时,当超过设置的秒数,就跳出阻塞,返回1,并继续执行下面语句。

-o必须是使用第一种格式时才可用,表示当执行command前关闭设置锁的FD,以使command的子进程不保持锁。

-c执行其后的comand。

 

flock 是对于整个文件的建议性锁。也就是说,如果一个进程在一个文件(inode)上放了锁,那么其它进程是可以知道的。它的第一个参数是文件描述符,在此文件描述符关闭时,锁会自动释放。而当进程终止时,所有的文件描述符均会被关闭。于是,很多时候就不用考虑解锁的事情。

 

 

使用的例子:

#!/bin/bash

{

 flock –n 3

  [$? –eq 1] && { echo fail ;exit}

 echo succeed

  #Doyour task here …

 

} 3 <> mylockfile

 

首先使用<>打开mylockfile 并定向到文件描述符3,而定向文件描述符是先于命令执行的,因此假如要执行的语句段中需要读写mylockfile文件,例如想获得上一个脚本实例的pid,并将此次的脚本实例的pid写入mylockfile。此时直接用>打开mylockfile会清空上次存入的内容,而用<打开mylockfile当它不存在时会导致一个错误。

 

其次,以非阻塞的方式打开mylockfile,flock –n 3,其中3是mylockfile的文件描述符,若能够正常获取锁(默认是排它锁),则继续往下执行,否则返回1,该返回码能够在接下来的语句中[ $? –eq 1 ] 进行判断,若为1,则输出失败并退出当前脚本。

 

 

Reference

http://linux.die.net/man/1/flock

0 0