如何确保应用程序运行的唯一性

一 简介 相信大家在开发脚本或者写程序的时候 ,大多会遇到如何判断已经有程序在运行的情况。比如设计备份binlog ,由于某个实例产生的binlog 数量大于备份的速度,在下一个时间点,会启动一个新的进程对binlog进行备份。那我们要怎么解决呢,本文分别从 shell和python的角度提出我的解决方法,同时也推荐《 Ensure a single instance of an application in Linux》[1],这里有比较详细的讨论。

二 shell 脚本的解决方法 利用mkdir 的特性 创建已经存在的文件目录则会失败。程序第一次运行的时候可以创建一个 /tmp/lock文件夹,标示当前已经运行一个程序,当启动第二个程序时,mkdir /tmp/lock 便会失败。

  1. #!/bin/bash
  2. mkdir /tmp/lock
  3. if [ $? -ne 0 ];then
  4. echo "there is tr script running .. "
  5. exit 1
  6. fi
  7. trap "rm -fr /tmp/lock " SIGINT SIGTERM
  8. sleep 50
  9. if [ -d /tmp/lock ];then
  10. rm -fr /tmp/lock
  11. echo "rm -fr /tmp/lock"
  12. fi

注意 linux中的trap命令是防止脚本异常终止 :被kill (不是kill -9) ,crtl+c 中断 比较详细的资料 《Linux命令之trap - 在脚本中处理信号》[2] 三 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 ,获取锁时会失败,并且及时退出程序。

  1. #!/usr/bin/python2.6
  2. #coding:utf8
  3. import time
  4. import fcntl
  5. import sys
  6. def is_running(file):
  7. lock_file=open(file,"w")
  8. try:
  9. fcntl.lockf(lock_file,fcntl.LOCK_EX|fcntl.LOCK_NB)
  10. print "给文件加锁 ,请等待10s..."
  11. except :
  12. print '文件加锁,无法执行,请稍后运行。'
  13. return None
  14. return lock_file
  15. if __name__ == "__main__":
  16. lockfile="/tmp/rsync_is_running"
  17. a=is_running(lockfile)
  18. if a is None :
  19. print "lock file failed , rsync is running .quit ..."
  20. sys.exit(0)
  21. else :
  22. print "lock file successed !!! "
  23. time.sleep(10)

测试例子: 会话一

会话二

其实还可以有很多其他的方式 比如 最容易想到的是根据 当前进程的 application_name.pid 或者

ps application_name | wc -l 来判断,不过使用ps 命令时,遇到和系统其他命令关键字一样的时候 ,就会不准。http://stackoverflow.com/ 中比较推荐使用pid ,各位读者朋友也可以提出自己的见解。欢迎讨论。

四 参考文章

[1] https://stackoverflow.com/questions/220525/ensure-a-single-instance-of-an-application-in-linux

[2] http://codingstandards.iteye.com/blog/836588

原文发表时间:2017-11-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏沈唁志

如何在CentOS 7上安装PostgreSQL关系数据库

PostgreSQL关系数据库系统是一个功能强大的,可扩展的,并符合标准的开源数据库平台。本指南将帮助您在CentOS 7 Linode上安装和配置Postgr...

18320
来自专栏张善友的专栏

SQL Server : Browser服务

SQL Server : Browser服务是SQL Server 2005新增的,简单的说,如果一个物理服务器上面有多个SQL Server实例,那么为了确保...

23150
来自专栏吴柯的运维笔记

使用XtraBackup工具实现数据库备份

一:安装XtraBackup软件包 1)安装依赖包perl-DBD-MySQL perl-Digest-MD5 libev # yum -y install ...

38350
来自专栏破晓之歌

Django框架中Mysql数据库连接 原

将settings.py文件中的Databases数据库连接部分设置如上,这里的USER和PASSWORD要和mysql里设置的一样,3306端口为默认,127...

12120
来自专栏ytkah

dedecms批量修改文章为待审核稿件怎么操作

  dedecms批量修改文章为待审核稿件要怎么操作呢?因为我们有时会出于某些原因要把文章暂时先隐藏掉,dedecms有一个比较好的功能是将文件状态设为未审核前...

31550
来自专栏醉生梦死

MySQL日志管理工具 mysqlbinlog

 [root@db02 data]# mysqlbinlog mysql_bin.000001

1.4K20
来自专栏技术博文

在Linux环境下mysql的root密码忘记解决方法

方法一: 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库。 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于...

35250
来自专栏杨建荣的学习笔记

MySQL备份恢复第二篇(r5笔记第6天)

MySQL中的数据恢复功能相比Oracle来说还是要单薄一些,而Oracle中的数据恢复相对来说自动化的程度要高一些。不过Mysql的二进制日志提供的信息很丰富...

36850
来自专栏Django Scrapy

mysql管理相关

查看数据库是否启动 ps -ef | grep mysqld 如果未启动 cd /usr/bin ./mysqld_safe & 想关闭mysql服务器...

38190
来自专栏喵了个咪的博客空间

基于PhalApi2的Redis拓展

基于PhalApi2的Redis拓展 ? 前言 Redis在PHP开发中运用场景已经无处不在,小到简单缓存大到数据库或消息队列都可以使用Redis来进行实现,基...

31750

扫码关注云+社区

领取腾讯云代金券