正文
Linux里的Crontab是一个好东西,但是它的默认最小执行频率是1分钟,但是我们在实际生产环境里有的时候遇到的脚本执行时间是大于1分钟的,这样就会出现一个很尴尬的情况,就是在1分钟过后,系统进程会出现多个脚本,neck and neck式的在后台运行,比如这样:
从上面的图可以看到,10点36分log499.sh
没有执行完毕,10点37又开始了执行了一个新的log499.sh
脚本。这种脚本冲突肯定不是我们所希望的,那么如何才能保证后台只是在一段时间里只执行一个脚本呢?
这个时候我们就要使用文件锁,flock
,这种方法要比判断pid高大上的多。
首先假设我们的脚本名字叫abc.sh,这个脚本文件的执行时间是要大于1分钟的,同时我们再设定一个锁文件,位置就叫/tmp/abc.lock
,这个文件可以是空的,然后crontab -e
,添加一句命令如下:
1
* * * * * flock -xn /tmp/abc.lock -c 'sh /路径/abc.sh >> /记录日志的路径 2>&1'
这个时候静候crontab启动abc.sh,通过ps -ef|grep abc
,发现在后台始终只有一个abc进程。
但是有的时候会有这样的一个问题,就是abc执行一次之后,在下一次该执行的时候却没有执行,好像crontab失效了一样,对于这样的情况,就需要添加下面的语句到abc.sh末尾:
1
2
3rm -rf /tmp/abc.lock #删除掉原有的锁文件
sleep n #睡n秒
touch /tmp/abc.lock #再新建一个锁文件
这样不断地更新lock锁文件,就会保证crontab每次都会按期执行。
这里要注意一下,里面我加了一句sleep n
,这里的n是为了跨分钟的存在,这是为了防止没有走到下一个分钟又会生成一个新的lock锁文件,这样还是会出现重复启动脚本的情况。
这里就涉及到flock的一个原理:在每一次执行任务的时候都会先去尝试取到锁文件,如果取到了锁文件,那么就会下一步,反之就会放弃执行。A任务在运行的时候已经占据了lock文件,那么B任务来了,发现没有lock了,就不会执行任务。
这里我们使用了flock的三个参数:
1
2
3-x, --exclusive: 获得一个独占锁
-n, --nonblock: 如果没有立即获得锁,直接失败而不是等待
-c, --command: 在shell中运行一个单独的命令
当然,flock还是有很多丰富的参数可以供各位使用,大家就各自去google一下吧。
参考资料
http://blog.csdn.net/fdipzone/article/details/38284009
http://chuansong.me/n/285635151949
https://segmentfault.com/q/1010000008039907