【发布时间】:2013-05-31 03:15:17
【问题描述】:
我有一个二进制文件,它是一个守护进程,它是用 C 语言开发的。我想在我的程序开头添加一个检查,以保证二进制文件只启动一次。我的二进制文件在 Linux 上运行。
有什么建议吗?
【问题讨论】:
-
我认为这是由stackoverflow.com/q/1599459/20270 回答的,虽然我很犹豫是否将其标记为重复。
我有一个二进制文件,它是一个守护进程,它是用 C 语言开发的。我想在我的程序开头添加一个检查,以保证二进制文件只启动一次。我的二进制文件在 Linux 上运行。
有什么建议吗?
【问题讨论】:
分叉并执行:
pidof nameOfProgram
如果它返回一个值,你就知道你的程序正在运行!
【讨论】:
pidof 你只知道一个同名(甚至不是同一个路径)的程序正在执行。 pidof 也很活泼,因为在 pidof 的执行和进程的启动之间没有锁定。这意味着如果您执行./mybin & ./mybin &,您的系统很可能会失败。
另一个经典的方法是拥有一个锁定文件——程序创建一个文件,但前提是该文件不存在。如果该文件确实存在,则假定该程序的另一个副本正在运行。因为程序在创建文件后可能会崩溃,所以更智能的版本可以检测到这种情况。
【讨论】:
common method 是将PID file 放入/var/run。在你的守护进程成功启动后,你 flock 将它的 PID 写入这个文件。启动时,检查此文件中的 PID 值(如果存在)。如果当前没有运行 PID,则应用程序可以安全启动。如果 PID 存在,请执行检查以查看该 PID 是否是可执行文件的实例。如果不是,启动也是安全的。您应该在退出时删除该文件,但这不是绝对必要的。
【讨论】:
flock主要是让你不用去检查PID是否存在,就好像你的程序在运行过程中一直保持着锁,它被锁住就说明进程存在。
在我看来,最好的方法是不这样做。让您的初始化方案序列化守护进程的实例:systemd、runit、supervise、upstart、launchd 等可以确保没有重复调用。
如果您需要“手动”调用您的守护程序,请尝试使用 linux 实用程序 flock(1) 或像 setlock 这样的第三方实用程序。这两个都将在一个(可能是继承的)锁定文件的保护下运行守护进程,该锁定文件在程序的生命周期内保持锁定状态。
如果您坚持将此功能添加到守护程序本身(在我看来,这是大多数守护程序不需要的复杂性),请选择一个锁定文件并专门保留它flock(2)d。与大多数 pidfile/进程表方法不同,这种方法不易竞争。与 POSIX 系统信号量不同,此机制将正确处理守护进程崩溃的情况(进程崩溃时锁消失)。
可能还有其他简单的序列化。如果你的守护进程绑定到一个套接字,你就知道 EADDRINUSE 可能意味着另一个实例正在运行......
【讨论】: