简介
相信大家在开发脚本或者写程序的时候 ,大多会遇到如何判断已经有程序在运行的情况。比如设计备份binlog ,由于某个实例产生的binlog 数量大于备份的速度,在下一个时间点,会启动一个新的进程对binlog进行备份。那我们要怎么解决呢,本文分别从 shell和python的角度提出我的解决方法,同时也推荐 《 Ensure a single instance of an application in Linux 》,这里有比较详细的讨论。
一 shell 脚本的解决方法
利用mkdir 的特性 创建已经存在的文件目录则会失败。程序第一次运行的时候可以创建一个 /tmp/lock文件夹,标示当前已经运行一个程序,当启动第二个程序时,mkdir /tmp/lock 便会失败。
注意 linux中的trap命令是防止脚本异常终止 :被kill (不是kill -9) ,crtl+c 中断 比较详细的资料 《Linux命令之trap - 在脚本中处理信号》http://codingstandards.iteye.com/blog/836588
二 python 脚本的解决方法
网上搜索python 锁定文件的时候,都会提示 fcntl 模块。Python的文件锁目前使用的是fcntl这个库,它实际上为 Unix上的ioctl,flock和fcntl 函数提供了一个接口。
fcntl模块的函数flock(file_handle, operation)
其中 file_handle 表示文件描述符,operation 指要进行的锁操作,有如下几种:
fcntl.LOCK_UN 解锁:删除floc()函数创建的锁
fcntl.LOCK_EX 排他锁:除加锁进程外其他进程没有对已加锁文件读写访问权限。
fcntl.LOCK_SH 共享锁:所有进程没有写访问权限,即使是加锁进程也没有。所有进程有读访问权限。
fcntl.LOCK_NB 非阻塞锁: 此参数意味着函数不能获得文件锁就立即返回,否则,如果使用LOCK_EX/LOCK_SH请求加锁不成功,则当前进程会等待获得文件锁。使用LOCK_NB可以在获得这个排他锁的情况下不阻塞该进程,LOCK_NB 也可以同LOCK_SH或LOCK_NB进行按位或(|)运算操作,比如fcnt.flock(file_handle,fcntl.LOCK_EX|fcntl.LOCK_NB),此时系统便不会阻塞当前的进程。
注意:
1. 对于文件的f.close() 操作会使文件锁失效;
2. 主进程结束后文件锁失效;
3. flock()的LOCK_EX是"劝告锁",系统内核不会强制检查锁的状态,需要在代码中进行文件操作的地方显式检查才能生效。
测试脚本
脚本中使用is_running 函数对文件加锁,time.sleep(10) 模拟长时间执行的程序,第一次运行lock.py 成功加锁,在程序运行期间 再次运行lock.py ,获取锁时会失败,并且及时退出程序。
测试例子:
会话一
会话二
三 小结
其实还可以有很多其他的方式 比如 最容易想到的 application_name.pid 或者ps application_name | wc -l 来判断,不过使用ps 命令时,遇到和系统其他命令关键字一样的时候 ,就会不准。http://stackoverflow.com/中比较推荐使用pid ,各位读者朋友也可以提出自己的见解。欢迎讨论。
相信大家在开发脚本或者写程序的时候 ,大多会遇到如何判断已经有程序在运行的情况。比如设计备份binlog ,由于某个实例产生的binlog 数量大于备份的速度,在下一个时间点,会启动一个新的进程对binlog进行备份。那我们要怎么解决呢,本文分别从 shell和python的角度提出我的解决方法,同时也推荐 《 Ensure a single instance of an application in Linux 》,这里有比较详细的讨论。
一 shell 脚本的解决方法
利用mkdir 的特性 创建已经存在的文件目录则会失败。程序第一次运行的时候可以创建一个 /tmp/lock文件夹,标示当前已经运行一个程序,当启动第二个程序时,mkdir /tmp/lock 便会失败。
- #!/bin/bash
- mkdir /tmp/lock
- if [ $? -ne 0 ];then
- echo "there is tr script running .. "
- exit 1
- fi
- trap "rm -fr /tmp/lock " SIGINT SIGTERM
- sleep 50
- if [ -d /tmp/lock ];then
- rm -fr /tmp/lock
- echo "rm -fr /tmp/lock"
- fi
二 python 脚本的解决方法
网上搜索python 锁定文件的时候,都会提示 fcntl 模块。Python的文件锁目前使用的是fcntl这个库,它实际上为 Unix上的ioctl,flock和fcntl 函数提供了一个接口。
fcntl模块的函数flock(file_handle, operation)
其中 file_handle 表示文件描述符,operation 指要进行的锁操作,有如下几种:
fcntl.LOCK_UN 解锁:删除floc()函数创建的锁
fcntl.LOCK_EX 排他锁:除加锁进程外其他进程没有对已加锁文件读写访问权限。
fcntl.LOCK_SH 共享锁:所有进程没有写访问权限,即使是加锁进程也没有。所有进程有读访问权限。
fcntl.LOCK_NB 非阻塞锁: 此参数意味着函数不能获得文件锁就立即返回,否则,如果使用LOCK_EX/LOCK_SH请求加锁不成功,则当前进程会等待获得文件锁。使用LOCK_NB可以在获得这个排他锁的情况下不阻塞该进程,LOCK_NB 也可以同LOCK_SH或LOCK_NB进行按位或(|)运算操作,比如fcnt.flock(file_handle,fcntl.LOCK_EX|fcntl.LOCK_NB),此时系统便不会阻塞当前的进程。
注意:
1. 对于文件的f.close() 操作会使文件锁失效;
2. 主进程结束后文件锁失效;
3. flock()的LOCK_EX是"劝告锁",系统内核不会强制检查锁的状态,需要在代码中进行文件操作的地方显式检查才能生效。
测试脚本
脚本中使用is_running 函数对文件加锁,time.sleep(10) 模拟长时间执行的程序,第一次运行lock.py 成功加锁,在程序运行期间 再次运行lock.py ,获取锁时会失败,并且及时退出程序。
- #!/usr/bin/python2.6
- #coding:utf8
- import time
- import fcntl
- import sys
- def is_running(file):
- lock_file=open(file,"w")
- try:
- fcntl.lockf(lock_file,fcntl.LOCK_EX|fcntl.LOCK_NB)
- print "给文件加锁 ,请等待10s..."
- except :
- print '文件加锁,无法执行,请稍后运行。'
- return None
- return lock_file
-
- if __name__ == "__main__":
- lockfile="/tmp/rsync_is_running"
- a=is_running(lockfile)
- if a is None :
- print "lock file failed , rsync is running .quit ..."
- sys.exit(0)
- else :
- print "lock file successed !!! "
- time.sleep(10)
会话一
会话二
三 小结
其实还可以有很多其他的方式 比如 最容易想到的 application_name.pid 或者ps application_name | wc -l 来判断,不过使用ps 命令时,遇到和系统其他命令关键字一样的时候 ,就会不准。http://stackoverflow.com/中比较推荐使用pid ,各位读者朋友也可以提出自己的见解。欢迎讨论。