我在哪里可以找到备受推崇的参考,详细说明在Unix上正确处理PID文件?
在Unix操作系统上,通常的做法是使用特殊的锁文件“锁定”程序(通常是一个守护程序):PID文件。
这是一个位于可预测位置的文件,通常为“/var/run/foo.pid”。程序应该在启动时检查PID文件是否存在,如果文件存在,则退出并显示错误。所以这是一种咨询性的协作锁定机制。
该文件包含一行文本,是当前持有锁的进程的数字进程ID(因此名称为“PID文件”);这样就可以轻松地自动将信号发送到持有锁的进程。
我找不到的是处理PID文件的预期或“最佳实践”行为的良好参考。有各种细微差别:如何实际锁定文件(不要打扰?使用内核?平台不兼容性怎么办?),处理陈旧锁(默默删除它们?何时检查?),何时获取并释放锁等等。
在哪里可以找到受尊重,最具权威性的参考(理想情况介绍在W. Richard Stevens的水平上)这个小主题?
答案 0 :(得分:21)
首先,所有现代UNIX /var/run
都不会在重新启动后持续存在。
处理PID文件的一般方法是在初始化期间创建它并从任何出口(普通处理程序或信号处理程序)中删除它。
有两种规范的方法可以自动创建/检查文件。这些天最主要的是用O_EXCL
标志打开它:如果文件已经存在,则调用失败。旧方法(在没有O_EXCL
的系统上是强制的)是使用随机名称创建它并链接到它。如果目标存在,链接将失败。
答案 1 :(得分:17)
据我所知,PID文件是一种惯例,而不是你可以找到一个受人尊敬的,主要是权威的来源。我能找到的最接近的是Filesystem Hierarchy Standard的this section。
This Perl library可能会有所帮助,因为看起来作者至少考虑过一些可能出现的问题。
我认为/ var / run下的文件通常由发行版维护者而不是守护进程的作者处理,因为发行版维护者有责任确保所有的init脚本能够很好地协同工作。我检查了Debian和Fedora的开发者文档,找不到任何详细的指南,但是你可以在开发者的邮件列表上获得更多信息。
答案 2 :(得分:11)
参见Kerrisk的The Linux Programming Interface,第55.6节"Running Just One Instance of a Program",它基于Stevens的Unix网络编程v2中的pidfile实现。
另请注意,pid文件的位置通常由发行版处理(通过init脚本),因此编写良好的守护程序将采用命令行参数来指定pid文件,并且不允许将其意外覆盖。配置文件。它还应该优雅地自己处理过时的pid文件(不应该使用O_EXCL)。应该使用fcntl()文件锁定 - 您可以假设守护程序的pidfile位于本地(非NFS)文件系统上。
答案 3 :(得分:7)
根据分发,它实际上是处理pidfile的init脚本。它会在启动时检查是否存在,在停止时检查等等。我不喜欢这样做。我编写自己的init脚本,通常不使用stanard init函数。
编写良好的程序(守护程序)将具有某种配置文件,说明应该写入此pidfile(如果有)。它还需要注意建立信号处理程序,以便在可以处理信号时,在正常或异常退出时清除PID文件。然后PID文件为init脚本提供正确的PID,以便它可以停止。
因此,如果pidfile在启动时已经存在,它对程序的一个非常好的指示,它先前崩溃了,应该做一些恢复工作(如果适用)。如果您有init脚本本身检查PID是否存在,或者取消链接,那么您可以在脚中拍摄该逻辑。
就名称空间而言,它应该遵循程序名称。如果你开始'foo-daemon',它将是foo-daemon.pid
您还应该探索/ var / lock / subsys,但这主要用于Red Hat风格。
答案 4 :(得分:0)
Red Hat 7上的systemd
软件包提供了一个手册页daemon(7)
,标题行为#34;编写和打包系统守护进程。"
此手册页讨论了旧样式" (SysV)和"新款" (systemd)守护进程。在新的样式中,systemd本身为您处理PID文件(如果这样配置的话)。但是,在旧样式中,手册页有这样的说法:
- 在守护进程中,编写守护进程PID(由getpid()返回) 到一个PID文件,例如/run/foobar.pid(对于一个假设的守护进程) " foobar")确保守护进程不能多次启动。 这必须以无竞争的方式实现,以便PID文件 仅在与PID同时验证时更新 以前存储在PID文件中的不再存在或属于a 外国进程。
醇>
您还可以阅读此手册页online。