/var/run/user/$UID 是 PID 文件的新 /var/run 吗?

TSG*_*TSG 13 pid file-location systemd

我有一个应用程序(以 root 身份作为服务运行),它在/var/run. 但我想知道这现在是否不再是最佳实践。

Linux 中 - 2012 年询问的替代 pid 文件而不是 /var/run 的存储位置,提问者询问是否应该将 PID 文件放入/var/run。不过,这很大程度上是在 systemd 出现之前,以及 systemd 操作系统从/var/run到 just 的转变/run(作为 systemd “ API 文件系统”之一并列在systemd 文件层次结构要求中)。

Lennart Poettering(和其他人)的XDG 基本目录规范之类的东西谈到了“特定于用户的非必要运行时文件和其他文件对象(例如套接字、命名管道……)”的其他地方。systemdfile-hierarchy手册页也是如此。

我在别处读到的内容给我的印象/var/run/user/$UID是systemd 操作系统上此类内容的标准位置。

人们可以找到许多其他的例子。

那么我的应用程序应该更改为使用/var/run/user/$UID吗?由于它是一项服务(没有活动会话),pam_systemd 会清除/删除目录吗?或者$XDG_RUNTIME_DIR?这是特定于 systemd 的东西吗?或者它是所有 Unices 的新标准?

现在在 systemd 操作系统上的最佳实践是什么?对于其他(非系统化,但类 Unix 的)操作系统也是如此吗?

Tin*_*ino 13

你问:

/var/run/user/$UID 是 PID 文件的新 /var/run 吗?

最简洁的答案是不”。

长答案仍然是“不”。

或者大声说清楚:传统的PID文件不能低于/run/user/$UID/(AKA /var/run/user/$UID/)。保留它们/run//run/package/像往常一样,/run/user/$UID/为会话服务提供完全不同的目的。

供参考:

  • 正如@Daniel B 所指出的,/var/run今天是一个指向/run. 这不是特定于systemd今天的大多数系统,并且可以在大多数系统中找到。如果您想与旧系统保持兼容,有两种解决方案:要么使用/var/run/代替/run/,要么让某人创建/run指向/var/run此类旧系统的软链接。

  • 另请注意,这/run/user/$UID/是特定于系统运行的systemd-logind。旧系统也不支持它。

为那些还不知道的人详细介绍:

有3种类型的服务:系统服务、用户服务和会话服务。所有 3 种类型都可以在后台或前台运行,因此这提供了 6 种变体。

前台系统服务传统上被启动/etc/inittab,如今伴随着systemd它们通过启动/etc/init/。前台系统服务通常不需要 PID 文件,因为它们由 控制init,如果失败可以重新生成。

后台系统服务传统上是由运行级脚本启动的/etc/rc.d/。这些通常需要 PID 文件,因为它们在后台运行,因此无法控制它们是否运行。PID 文件非常容易出错(因为不能保证服务终止后 PID 保持空闲),并且在 rc-script 需要关闭服务时用于再次查找已启动的服务。这些 PID 文件过去/var/run和现在都在/run/package/(或者,如果每个包只有一个文件,则在/run/package.pid.

用户服务是由用户启动的服务,需要在用户会话之外继续存在。例如,一个 Minecraft 服务器,或类似使用短期会话按需触发的长期 SAP 查询过程。它们与系统服务有点不同,因为它们不能使用/run/. 相反,他们需要使用/tmp/, 或下面的某个目录$HOME(如果$HOME是网络共享,在多台计算机之间共享,这是有问题的)。

前台用户服务有时会有点问题,因为它们通常需要一个tty,因此如果用户注销,它们将终止。因此,有很多方法可以让它们在用户离开后继续存在,例如nohupscreen。但甚至可以有一些异国情调的变体,如socat tcp-connect:host:port exec:service.sh,pty.

前台用户服务的另一个变体是存在于用户中的 cron 作业crontab。然而,这些 cronjob 也可以是后台服务,例如,如果它们不应该并行运行,即使一个进程超过了时间,当 cron 的下一次调用完成时。

后台用户服务与后台系统服务存在同样的问题,因为它们需要跟踪已经运行的服务并控制已经运行的服务。在过去,由于需要使用/tmp每个人都能够创建文件和目录的地方,这导致了各种问题和修复程序,例如目录遍历攻击等。

然而,这还没有改变,因为/run/user/$UID/这并不适用于此类用户服务。它旨在解决会话服务的一个更棘手的问题。

会话服务是一种服务,通常在用户登录时启动,在用户注销时停止。这听起来很简单,但如果每个用户允许的会话不止一个,则会获得动力。难以解决的问题是:“会话何时真正结束”?

会话从第一次登录开始。这很容易理解。但不一定会在此登录注销时结束!因此会话服务可以在第一次登录(或稍后)时启动,但通常需要继续运行,直到用户的最后一个会话注销。

前台会话服务通常是简单的变体。就像 X-Windowdbus服务一样,它以图形登录方式启动和终止。但是,如果您开始打印一个巨大的 PDF,您肯定希望这项工作要么成功完成,要么干净利落地终止,而不会留下任何碎片,对吧?

这些类型的会话服务要么需要继续在后台运行,要么在服务被击落后如果出现意外死亡,必须有某种方法进行清理。在我们的移动世界中,事情经常消失。想想你的显示器。您可以随时插入和拔出显示器。无需重新启动计算机。但是,如果拔掉所有屏幕,会发生什么?好吧,X11 当然死了。对于在 X11 会话中运行的某些用户服务,这是意外发生的,可能是在较长时间运行的任务中。

这是/run/user/$UID/派上用场的地方,因为在最后一个用户会话完成后会自动擦除此目录。因此,服务可以相信,用户背后存储的所有内容都会被清理干净/run/user/$UID/

所以所有与会话相关的服务都应该使用这个目录。

另请注意,我们dbus今天有。因此,您不再需要依赖 PID 文件来确定某个服务是否正在运行。对于会话服务尤其如此,因为有一种叫做“会话”的东西,它可以让您更好地处理事情,例如使用共享内存段或可以存在于/run/user/$UID/.

事情并不容易。为了让它更复杂一些screentmux或者ssh(从外壳中分叉出来的那个)有两个方面,一方面是用户服务(即守护进程),另一方面是会话服务(tty)。虽然它们通常绑定到一个会话,但不一定总是如此。例如,如果您使用ssh端口转发并退出 shell,则ssh保持打开状态,直到最后一个转发的端口关闭。只要其他端口保持活动状态,您甚至可以打开新端口。在这种“双重”服务的情况下,PID 文件之类的东西可能会派上用场,在这种情况下,它甚至可能位于/run/user/$UID/.

(请注意,cron它可用于打开用户会话,因此可能/run/user/$UID/也可用于 cronjobs。但如果是这种情况,/run/user/$UID/则在所有 cronjobs 完成后再次有资格进行清理。这可能意味着传递的文件消失了在其他地方,与他们居住时不同/tmp/,因为只有重新启动才能无条件地删除那里的文件。)

把它们加起来:

如果你有一个设计合理的服务,你将永远不需要/run/user/$UID/在 . .

因此,如果您发现您的服务需要 PID 文件,则很可能最终会得到类似/run/package/,/run/package.pid/tmp/package-$UID/.

/run/user/$UID/当您想确保文件在用户完全注销后立即消失时才使用。另请注意,root用户并不总是登录,因此很可能没有/run/user/0/.

而且,请永远不要在/run/user/自己下面创建目录!

希望现在一切都那么美好和清晰。但我有一点要承认:

我骗了你。我是故意这样做的(但没有恶意)。

作为会话(从systemd-logind的角度来看)不仅绑定到login. 是的,login当然涉及到类似的事情,但事情要复杂得多:

https://dvdhrm.wordpress.com/2013/08/24/session-management-on-linux/

然而:

  • 对于此处的帖子(简短但错误的故事),您的问题的答案是“否”。

  • 幸运的是,关于会话的长期(和真实)背景(见链接),答案仍然是“不”。

  • 仅在一些非常少且非常特殊的情况下,出于非常明确的目的,您可能会考虑将 PID 文件放入/run/user/$UID/.

祝你今天过得愉快。