确保Linux中应用程序的单实例

2024-10-21 09:14:00
admin
原创
119
摘要:问题描述:我正在使用 WxPython 开发 GUI 应用程序,但我不知道如何确保在机器上任何给定时间只有一个应用程序副本在运行。由于应用程序的性质,多次运行没有任何意义,并且会很快失败。在 Win32 下,我可以简单地创建一个命名互斥体并在启动时检查它。不幸的是,我不知道 Linux 中有什么工具可以做到这...

问题描述:

我正在使用 WxPython 开发 GUI 应用程序,但我不知道如何确保在机器上任何给定时间只有一个应用程序副本在运行。由于应用程序的性质,多次运行没有任何意义,并且会很快失败。在 Win32 下,我可以简单地创建一个命名互斥体并在启动时检查它。不幸的是,我不知道 Linux 中有什么工具可以做到这一点。

我正在寻找一种可以在应用程序意外崩溃时自动释放的功能。我不想因为应用程序崩溃而让用户不得不手动删除锁定文件。


解决方案 1:

正确的做法是使用咨询锁定;在 Python 中,这可以在模块flock(LOCK_EX)中找到。fcntl

与 pidfile 不同,当您的进程由于任何原因死亡时,这些锁总是会自动释放,不存在与文件删除相关的竞争条件(因为不需要删除文件释放锁),并且没有机会让其他进程继承 PID,从而看起来验证了陈旧的锁。

如果您想要非正常关机检测,您可以在获取锁之后将标记(例如,对于传统主义者来说,是您的 PID)写入文件,然后在正常关机之前(在持有锁的情况下)将文件截断为 0 字节状态;因此,如果没有持有锁并且文件非空,则表明发生了非正常关机。

解决方案 2:

使用模块完成锁定解决方案fcntl

import fcntl
pid_file = 'program.pid'
fp = open(pid_file, 'w')
try:
    fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
    # another instance is running
    sys.exit(1)

解决方案 3:

有几种常见的技术,包括使用信号量。我看到最常用的是在启动时创建一个包含正在运行的进程的 pid 的“pid 锁定文件”。如果程序启动时该文件已经存在,则打开它并获取其中的 pid,检查是否有具有该 pid 的进程正在运行,如果是,则检查 /proc/ pid中的 cmdline 值以查看它是否是程序的实例,如果是,则退出,否则用您的 pid 覆盖该文件。pid 文件的常用名称是application_name.pid

解决方案 4:

wxWidgets 为此提供了一个 wxSingleInstanceChecker 类:wxPython doc或wxWidgets doc。wxWidgets doc 中有 C++ 示例代码,但 python 等效代码应如下所示(未经测试):

  name = "MyApp-%s" % wx.GetUserId()
  checker = wx.SingleInstanceChecker(name)
  if checker.IsAnotherRunning():
      return False

解决方案 5:

这建立在用户zgoda的回答之上。它主要解决了与锁定文件的写访问有关的棘手问题。特别是,如果锁定文件首先由 创建,则由于用户 缺乏写权限,另一个用户将无法成功重写此文件。显而易见的解决方案似乎是为每个人创建具有写权限的文件。此解决方案还建立在我的另一个答案之上,该答案与创建具有此类自定义权限的文件有关。这个问题在现实世界中很重要,因为您的程序可能由包括 在内的任何用户运行。root`foofooroot`

import fcntl, os, stat, tempfile

app_name = 'myapp'  # <-- Customize this value

# Establish lock file settings
lf_name = '.{}.lock'.format(app_name)
lf_path = os.path.join(tempfile.gettempdir(), lf_name)
lf_flags = os.O_WRONLY | os.O_CREAT
lf_mode = stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH  # This is 0o222, i.e. 146

# Create lock file
# Regarding umask, see https://stackoverflow.com/a/15015748/832230
umask_original = os.umask(0)
try:
    lf_fd = os.open(lf_path, lf_flags, lf_mode)
finally:
    os.umask(umask_original)

# Try locking the file
try:
    fcntl.lockf(lf_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
    msg = ('Error: {} may already be running. Only one instance of it '
           'can run at a time.'
           ).format('appname')
    exit(msg)

上述代码的一个限制是,如果锁文件已经存在且具有意外的权限,则不会更正这些权限。

我本来想将/var/run/<appname>/其用作锁定文件的目录,但创建此目录需要root权限。您可以自行决定使用哪个目录。

请注意,不需要打开锁定文件的文件句柄。

解决方案 6:

以下是基于 TCP 端口的解决方案:

# Use a listening socket as a mutex against multiple invocations
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 5080))
s.listen(1)

解决方案 7:

查找与 unix 上的 SYSV 信号量接口的 Python 模块。信号量具有 SEM_UNDO 标志,如果进程崩溃,它将导致释放进程所持有的资源。

否则,正如 Bernard 建议的那样,你可以使用

import os
os.getpid()

并将其写入 /var/run/ application_name .pid。进程启动时,应该检查 /var/run/ application_name .pid 中的 pid 是否在 ps 表中,如果是则退出,否则将自己的 pid 写入 /var/run/ application_name .pid。下面的 var_run_pid 就是你从 /var/run/ application_name .pid中读取的 pid

cmd = "ps -p %s -o comm=" % var_run_pid
app_name = os.popen(cmd).read().strip()
if len(app_name) > 0:
    Already running

解决方案 8:

semaphore.h我认为,在-- sem_open()、等 --中定义的函数集sem_trywait()是 POSIX 等效的。

解决方案 9:

如果您创建一个锁文件并将 pid 放入其中,您可以根据它检查您的进程 id 并判断是否崩溃,不是吗?

我个人没有这样做过,所以请酌情考虑。:p

解决方案 10:

您可以使用“pidof”实用程序吗?如果您的应用程序正在运行,pidof 会将应用程序的进程 ID 写入标准输出。如果没有,它将打印换行符 (LF) 并返回错误代码。

示例(来自 bash,为简单起见):

linux# pidof myapp
8947
linux# pidof nonexistent_app

linux#

解决方案 11:

目前最常见的方法是将一个名为 [application].pid 的文件放入 /var/run/,该文件仅包含正在运行的进程或父进程的 PID。作为替代方案,您可以在同一目录中创建一个命名管道,以便能够向活动进程发送消息,例如打开一个新文件。

解决方案 12:

当您希望能够将后续尝试实例的命令行参数传递给第一个实例时,我已创建了一个用于运行此类应用程序的基本框架。如果实例未找到已在预定义端口上监听的实例,它将开始监听该端口。如果实例已存在,它将通过套接字发送其命令行参数并退出。

带解释的代码

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用