自动创建pid文件,并加锁

本文介绍了如何使用Python实现进程锁定文件,确保同一进程只运行一次实例,避免资源冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



点击(此处)折叠或打开

  1. #!/usr/bin/env python
  2. #coding=utf-8
  3. import sys
  4. import os
  5. import re
  6. import traceback
  7. import fcntl

  8. class PidFile():
  9.     def __init__(self, file = None):
  10.         if file == None:
  11.             argv0_list = sys.argv[0].split("\\")
  12.             scname = argv0_list[len(argv0_list) - 1]
  13.             if re.search(".py$", scname):
  14.             scname = scname[0:-3]
  15.             self.file = "/tmp/%s.pid" % (scname)
  16.         else:
  17.             self.file = file
  18.         self.pidfile = None

  19.     def _create(self, file):
  20.         f = open(file, "w")
  21.         pid = os.getpid()
  22.         f.write("%s" % (pid))
  23.         f.close()

  24.     def __enter__(self):
  25.         if not os.path.isfile(self.file):
  26.             self._create(self.file)
  27.         self.pidfile = open(self.file, 'a+')
  28.         try:
  29.             fcntl.flock(self.pidfile.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
  30.             return True
  31.         except:
  32.             traceback.print_exc()
  33.             fpid = open(self.file, "r").read()
  34.             raise SystemExit("Process id %s Already running , pid to %s " % (fpid, self.file))
  35.         return False    

  36.     def __exit__(self, *args):
  37.         try:
  38.             self.pidfile.close()
  39.         except :
  40.             pass
  41.         os.remove(self.file)


  42. if __name__ == "__main__":
  43.     # use
  44.     with PidFile() as t:
  45.         print "lock file %s" % (file)
  46.         time.sleep(10)
  47.     exit(0)

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26250550/viewspace-1816377/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26250550/viewspace-1816377/

<think>嗯,用户问的是只用文件锁能否实现控制唯一实例。我需要先回忆一下文件锁的基本机制。文件锁通常分为共享锁和排他锁,排他锁能防止其他进程同时获取锁,可能用来确保同一时间只有一个实例运行。不过可能存在哪些问题呢? 首先,进程意外终止时,文件锁会自动释放吗?比如进程崩溃或者被kill掉,操作系统应该会处理锁的释放,但不确定是否所有情况都可靠。比如,如果程序在持有锁时突然断电,这时候文件锁可能不会释放,导致下次启动时无法获取锁,即使没有实例在运行。 其次,不同用户或不同挂载点的文件系统,文件锁是否有效?比如,如果程序在多个用户下运行,每个用户可能有不同的文件路径,这时候同一个锁文件可能无法被其他用户访问。或者,如果锁文件位于NFS等网络文件系统上,文件锁的行为可能不一致,导致锁失效。 还有竞争条件的问题。假设两个进程同时检查锁文件是否存在,然后尝试创建,可能会有竞争。但使用文件锁的话,创建加锁应该是原子操作?比如,在打开文件时使用O_EXCL标志,可以确保原子性地创建文件加锁,避免竞争条件。 另外,锁文件的管理问题。如果程序异常退出,没有正确删除锁文件,可能导致残留文件,下次启动时误判已有实例。虽然文件锁在进程结束后会被释放,但文件本身可能仍然存在,需要程序在启动时处理这种情况,比如检查锁文件是否存在,尝试获取锁,如果获取失败再处理。 还有不同编程语言或操作系统对文件锁的实现差异。比如,Windows和Linux在处理文件锁时可能有所不同,可能会影响跨平台应用程序的唯一实例控制。 有没有其他方法可以结合文件锁使用,提高可靠性?比如,除了文件锁外,还可以检查进程列表,或者使用命名互斥量、信号量等系统级资源。特别是跨平台的情况,可能需要使用更高级的抽象机制。 总结来说,文件锁在大多数情况下可以实现唯一实例控制,但需要考虑异常情况、文件系统差异、竞争条件以及锁文件的管理。为了更可靠,可能需要结合其他方法,比如检查进程ID或者使用操作系统提供的互斥机制。</think>好的,让我们逐步分析如何通过文件锁实现程序唯一实例控制,以及需要注意的问题: 1. **基本原理** - 通过创建特定锁文件(如 `/tmp/myapp.lock`) - 使用 `fcntl` 系统调用对文件加排他锁 - 示例代码片段: ```python import fcntl lockfile = open('/tmp/myapp.lock', 'w') try: fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: print("已有实例在运行") exit(1) ``` 2. **优势分析** - 跨平台兼容性:在 Linux/Unix 系统上表现稳定 - 自动释放机制:进程终止时系统自动释放锁 - 简单高效:不需要复杂IPC机制 3. **关键注意事项** - **文件残留问题**: - 异常退出可能导致空文件残留 - 解决方案:启动时先尝试获取锁,失败后校验文件状态 - **NFS风险**: - 网络文件系统锁可能不可靠 - 应对方案:改用本地临时目录 `/var/run` - **权限控制**: - 多用户环境需设置文件权限(如 `0o600`) - **原子操作**: - 必须同时完成文件创建加锁操作 - 避免使用存在性检查(`if os.path.exists()`)的竞态条件 4. **增强方案** - **双重验证机制**: ```python def check_instance(): # 文件锁验证 if not get_file_lock(): return False # 进程列表二次验证 for pid in psutil.pids(): try: if 'myapp' in psutil.Process(pid).name(): return False except: pass return True ``` - **心跳机制**:定期更新文件时间戳,应对僵尸锁 - **安全清理**:启动时检查文件最后修改时间,超时后强制解锁 5. **替代方案对比** | 方法 | 可靠性 | 复杂度 | 跨平台 | 僵尸处理 | |---------------|--------|--------|--------|----------| | 文件锁 | ★★★☆ | ★☆☆ | ★★☆ | 自动 | | 命名管道 | ★★★☆ | ★★☆ | ★★☆ | 需处理 | | TCP端口绑定 | ★★★★ | ★★☆ | ★★★☆ | 自动 | | 系统信号量 | ★★★★☆ | ★★★☆ | ★☆☆ | 需处理 | | 进程间互斥量 | ★★★★★ | ★★★★ | ★★☆ | 自动 | 6. **最佳实践建议** - 开发阶段:优先使用文件锁快速实现 - 生产环境:结合TCP端口检查(`socket.bind(('localhost', 12345))`) - 关键系统:使用操作系统提供的互斥对象(如Linux的flock,Windows的Mutex) 结论:文件锁可以作为轻量级解决方案,但在高可靠要求的场景建议采用组合方案。对于服务类程序推荐使用TCP端口绑定方式,既保证可靠性又便于后续扩展远程控制功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值