在哪里可以找到备受推崇的参考资料,其中详细介绍了 Unix 上 PID 文件的正确处理?
在 Unix 操作系统上,通常的做法是使用特殊的锁定文件:PID 文件来“锁定”程序(通常是守护程序)。
这是一个位于可预测位置的文件,通常是“/var/run/foo.pid”。 程序应该在启动时检查 PID 文件是否存在,如果文件存在,则退出并出错。 所以它是一种咨询式、协作式锁定机制。
该文件包含一行文本,是当前持有锁的进程的数字进程 ID(因此称为“PID 文件”); 这提供了一种简单的方法来自动向持有锁的进程发送信号。
我找不到关于处理 PID 文件的预期或“最佳实践”行为的良好参考。 有各种细微差别:如何实际锁定文件(不麻烦?使用内核?平台不兼容怎么办?),处理过时的锁(默默地删除它们?何时检查?),何时获取和释放锁,等等。
我在哪里可以找到关于这个小主题的最受尊敬、最权威的参考资料(最好是 W. Richard Stevens 的水平)?
Where can I find a well-respected reference that details the proper handling of PID files on Unix?
On Unix operating systems, it is common practice to “lock” a program (often a daemon) by use of a special lock file: the PID file.
This is a file in a predictable location, often ‘/var/run/foo.pid’. The program is supposed to check when it starts up whether the PID file exists and, if the file does exist, exit with an error. So it's a kind of advisory, collaborative locking mechanism.
The file contains a single line of text, being the numeric process ID (hence the name “PID file”) of the process that currently holds the lock; this allows an easy way to automate sending a signal to the process that holds the lock.
What I can't find is a good reference on expected or “best practice” behaviour for handling PID files. There are various nuances: how to actually lock the file (don't bother? use the kernel? what about platform incompatibilities?), handling stale locks (silently delete them? when to check?), when exactly to acquire and release the lock, and so forth.
Where can I find a respected, most-authoritative reference (ideally on the level of W. Richard Stevens) for this small topic?
发布评论
评论(5)
首先,在所有现代 UNIX 上,
/var/run
不会在重新启动后持续存在。处理 PID 文件的一般方法是在初始化期间创建它并从任何退出(正常退出或信号处理程序)中删除它。
有两种原子地创建/检查文件的规范方法。 目前主要的方法是使用
O_EXCL
标志打开它:如果文件已经存在,则调用失败。 旧的方法(在没有O_EXCL
的系统上是强制的)是使用随机名称创建它并链接到它。 如果目标存在,链接将失败。First off, on all modern UNIXes
/var/run
does not persist across reboots.The general method of handling the PID file is to create it during initialization and delete it from any exit, either normal or signal handler.
There are two canonical ways to atomically create/check for the file. The main one these days is to open it with the
O_EXCL
flag: if the file already exists, the call fails. The old way (mandatory on systems withoutO_EXCL
) is to create it with a random name and link to it. The link will fail if the target exists.据我所知,PID 文件是一种约定,而不是您可以找到受人尊敬的、最权威的来源的东西。 我能找到的最接近的是文件系统层次结构标准的本节。
这个 Perl 库 可能会有所帮助,因为它看起来像作者在至少考虑到一些可能出现的问题。
我相信 /var/run 下的文件通常由发行版维护者而不是守护程序的作者处理,因为发行版维护者有责任确保所有初始化脚本都能很好地协同工作。 我检查了 Debian 和 Fedora 的开发人员文档,但找不到任何详细的指南,但您也许可以在他们的开发人员邮件列表上获得更多信息。
As far as I know, PID files are a convention rather than something that you can find a respected, mostly authoritative source for. The closest I could find is this section of the Filesystem Hierarchy Standard.
This Perl library might be helpful, since it looks like the author has at least given thought to some issues than can arise.
I believe that files under /var/run are often handled by the distro maintainers rather than daemons' authors, since it's the distro maintainers' responsibility to make sure that all of the init scripts play nice together. I checked Debian's and Fedora's developer documentation and couldn't find any detailed guidelines, but you might be able to get more info on their developers' mailing lists.
请参阅 Kerrisk 的 Linux 编程接口,第 55.6 节 “仅运行一个程序的一个实例”,它基于 Stevens 的《Unix 网络编程,v2》中的 pidfile 实现。
另请注意,pidfile 的位置通常由发行版处理(通过 init 脚本),因此编写良好的守护进程将采用命令行参数来指定 pidfile,并且不允许配置文件意外覆盖它。 它还应该自行妥善处理过时的 pid 文件(不应使用 O_EXCL)。 应使用 fcntl() 文件锁定——您可以假设守护程序的 pidfile 位于本地(非 NFS)文件系统上。
See Kerrisk's The Linux Programming Interface, section 55.6 "Running Just One Instance of a Program" which is based on the pidfile implementation in Stevens' Unix Network Programming, v2.
Note also that the location of the pidfile is usually something handled by the distro (via an init script), so a well written daemon will take a command line argument to specify the pidfile and not allow this to be accidentally overridden by a configuration file. It should also gracefully handle a stale pid file by itself (O_EXCL should not be used). fcntl() file locking should be used--you may assume that a daemon's pidfile is located on a local (non-NFS) filesystem.
根据发行版的不同,实际上是处理 pidfile 的 init 脚本。 它在启动时检查是否存在,在停止时删除等等。我不喜欢这样做。 我编写自己的初始化脚本,通常不使用标准初始化函数。
一个编写良好的程序(守护进程)将有某种配置文件,说明该 pid 文件(如果有)应该写入何处。 它还会注意建立信号处理程序,以便在正常或异常退出时只要可以处理信号,就会清除 PID 文件。 然后 PID 文件为 init 脚本提供正确的 PID,以便它可以停止。
因此,如果 pidfile 在启动时已经存在,那么它可以很好地指示程序之前崩溃过,并且应该执行某种恢复工作(如果适用)。 如果您让 init 脚本本身检查 PID 是否存在或取消链接,那么您就相当于搬起石头砸自己的脚。
就名称空间而言,它应该遵循程序名称。 如果您要启动“foo-daemon”,它将是 foo-daemon.pid
您还应该探索 /var/lock/subsys,但是它主要用于 Red Hat 版本。
Depending on the distribution, its actually the init script that handles the pidfile. It checks for existence at starting, removes when stopping, etc. I don't like doing it that way. I write my own init scripts and don't typically use the stanard init functions.
A well written program (daemon) will have some kind of configuration file saying where this pidfile (if any) should be written. It will also take care to establish signal handlers so that the PID file is cleaned up on normal, or abnormal exit, whenever a signal can be handled. The PID file then gives the init script the correct PID so it can be stopped.
Therefore, if the pidfile already exists when starting, its a very good indicator to the program that it previously crashed and should do some kind of recovery effort (if applicable). You kind of shoot that logic in the foot if you have the init script itself checking for the existence of the PID, or unlinking it.
As far as the name space, it should follow the program name. If you are starting 'foo-daemon', it would be foo-daemon.pid
You should also explore /var/lock/subsys, however that's used mostly on Red Hat flavors.
Red Hat 7 上的
systemd
软件包提供了一个手册页daemon(7)
,其标题行为“编写和打包系统守护程序”。本手册页讨论“旧式”(SysV) 和“新式”(systemd) 守护进程。 在新的风格中,systemd 本身会为您处理 PID 文件(如果已配置)。 然而,在旧风格中,手册页是这样说的:
您还可以在线阅读此手册页。
The
systemd
package on Red Hat 7 provides a man pagedaemon(7)
with the header line "Writing and packaging system daemons."This man page discusses both "old style" (SysV) and "new style" (systemd) daemonization. In new style, systemd itself handles the PID files for you (if so configured to do so). However, in old style, the man page has this to say:
You can also read this man page online.