【问题标题】:Reference for proper handling of PID file on Unix在 Unix 上正确处理 PID 文件的参考
【发布时间】:2010-10-15 20:35:57
【问题描述】:

我在哪里可以找到备受推崇的参考,详细说明如何在 Unix 上正确处理 PID 文件?

在 Unix 操作系统上,通常的做法是使用特殊的锁定文件“锁定”程序(通常是守护程序):PID 文件。

这是一个位于可预测位置的文件,通常是“/var/run/foo.pid”。该程序应该在启动时检查 PID 文件是否存在,如果该文件存在,则退出并出错。所以这是一种建议性的协作锁定机制。

该文件包含单行文本,是当前持有锁的进程的数字进程 ID(因此称为“PID 文件”);这提供了一种简单的方法来自动向持有锁的进程发送信号。

我找不到关于处理 PID 文件的预期或“最佳实践”行为的良好参考。有各种细微差别:如何实际锁定文件(不要打扰?使用内核?平台不兼容怎么办?),处理陈旧的锁(静默删除它们?何时检查?),何时获取和释放锁,等等。

我在哪里可以找到关于这个小主题的受人尊敬、最权威的参考文献(最好是 W. Richard Stevens 的水平)?

【问题讨论】:

  • $XDG_RUNTIME_DIR 如果以 1000+ uid 的用户身份运行,则应该放置 pid 文件。

标签: locking daemon unix


【解决方案1】:

Red Hat 7 上的 systemd 软件包提供了一个手册页 daemon(7),其标题行是“编写和打包系统守护进程”。

本手册页讨论了“旧式”(SysV) 和“新式”(systemd) 守护进程。在新风格中,systemd 本身会为您处理 PID 文件(如果配置为这样做)。但是,在旧式中,手册页有这样的说法:

  1. 在守护进程中,写入守护进程 PID(由 getpid() 返回) 到 PID 文件,例如 /run/foobar.pid(对于假设的守护进程 "foobar") 以确保守护程序不能多次启动。 这必须以无竞争的方式实现,以便 PID 文件是 只有在验证 PID 的同时才更新 以前存储在 PID 文件中的不再存在或属于某个 国外进程。

您也可以阅读此手册页online

【讨论】:

    【解决方案2】:

    根据发行版的不同,它实际上是处理 pidfile 的 init 脚本。它在开始时检查是否存在,在停止时删除等等。我不喜欢那样做。我编写自己的初始化脚本,通常不使用标准初始化函数。

    一个编写良好的程序(守护进程)会有某种配置文件,说明该 pidfile(如果有的话)应该写在哪里。它还将注意建立信号处理程序,以便在可以处理信号时在正常或异常退出时清理 PID 文件。然后 PID 文件为 init 脚本提供正确的 PID,以便它可以停止。

    因此,如果 pidfile 在启动时已经存在,则它可以很好地指示程序之前崩溃并且应该进行某种恢复工作(如果适用)。如果您让 init 脚本本身检查 PID 的存在或取消链接,那么您就会在脚下拍出这种逻辑。

    就名称空间而言,它应该跟在程序名称之后。如果您正在启动 'foo-daemon',它将是 foo-daemon.pid

    您还应该探索 /var/lock/subsys,但它主要用于 Red Hat 风格。

    【讨论】:

      【解决方案3】:

      参见 Kerrisk 的 The Linux Programming Interface,第 55.6 节 "Running Just One Instance of a Program",它基于 Stevens 的 Unix Network Programming, v2 中的 pidfile 实现。

      还要注意,pidfile 的位置通常由发行版处理(通过 init 脚本),因此编写良好的守护进程将使用命令行参数来指定 pidfile,并且不允许它被意外覆盖配置文件。它还应该自己优雅地处理陈旧的 pid 文件(不应使用 O_EXCL)。应该使用 fcntl() 文件锁定——您可以假设守护进程的 pidfile 位于本地(非 NFS)文件系统上。

      【讨论】:

      • 如果网上有这方面的信息,请将“Linux 编程接口”和/或“第 55.6 节”转为锚文本链接到我们可以阅读更多内容的地方。
      【解决方案4】:

      首先,在所有现代 UNIX 上,/var/run 不会在重新启动后持续存在。

      处理 PID 文件的一般方法是在初始化期间创建它,然后从任何退出(正常或信号处理程序)中删除它。

      有两种规范的方法可以自动创建/检查文件。这些天主要是用O_EXCL 标志打开它:如果文件已经存在,则调用失败。旧方法(在没有O_EXCL 的系统上是强制性的)是使用随机名称创建它并链接到它。如果目标存在,链接将失败。

      【讨论】:

      • “有两种规范的方法可以自动创建/检查文件。”这正是我的问题所在:这个经典在哪里被规范地记录下来,与其他人的相互矛盾的建议相比,它的权威性是什么?
      • 不幸的是,许多 UNIX 操作方法是在文化中流传下来的。阅读 POSIX.1 中描述的系统调用的手册页(这些在手册第 2 节中,令人困惑的是)仅揭示了一些适合锁定的内容。由于flock() 不受信任,因此只剩下这两个和一个涉及mkdir。
      • 一个公平的问题是“为什么flock() 不受信任。”答案是这些年来有太多损坏的系统,而且无论如何它都无法在 nfs 上正常工作(nfslock 协议本身就存在思想分裂问题)。
      【解决方案5】:

      据我所知,PID 文件是一种约定,而不是您可以找到受人尊敬的、主要是权威来源的东西。我能找到的最接近的是文件系统层次标准的this section

      This Perl library 可能会有所帮助,因为看起来作者至少考虑了一些可能出现的问题。

      我相信 /var/run 下的文件通常由发行版维护者而不是守护程序的作者处理,因为发行版维护者有责任确保所有 init 脚本一起运行良好。我查看了 Debian 和 Fedora 的开发人员文档,找不到任何详细的指南,但您可以在他们的开发人员邮件列表中获得更多信息。

      【讨论】:

      • 谢谢。其他论坛的共识似乎也没有对此的规范参考。 (FHS 简要提及文件位置和内容,并没有提及行为。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-06
      • 1970-01-01
      相关资源
      最近更新 更多