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

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

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

Linux - 存储 pid 文件的替代位置(而不是 /var/run),在 2012 年提出,提问者问 PID 文件是否应该放在/var/run其中。不过,那主要是在 systemd 出现之前,以及 systemd 操作系统从转变为/var/run仅仅/run(作为 systemd 之一)之前。API 文件系统“并列于systemd 文件层次结构要求)。

类似的事情XDG 基础目录规范Lennart Poettering (和其他人) 讨论了“用户特定的非必要运行时文件和其他文件对象(例如套接字、命名管道等)”的其他地方。systemdfile-hierarchy手册页

我在其他地方读到的给我的印象/var/run/user/$UID新的systemd 操作系统上此类内容的标准位置。

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

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

什么是最佳实践如今在 systemd 操作系统上?一般来说其他(非 systemd,但类似 ​​Unix)操作系统也是如此?

答案1

你问:

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

最简洁的答案是不”。

长话短说,答案仍然是“不”。

或者大声明确地说:传统 PID 文件不得低于/run/user/$UID/(又名/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 脚本需要关闭服务时,它们会用于再次查找已启动的服务。这些 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用户中。但是,这些 cron 作业也可以是后台服务,例如,如果它们不应该并行运行,即使一个进程超过了 cron 下一次调用的时间。

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

然而这一点至今仍未改变,因为/run/user/$UID/它并非为此类用户服务而设计的。它旨在解决会话服务中更为棘手的问题。

会话服务是一种通常在用户登录时启动并在用户注销时停止的服务。这听起来很简单,但如果每个用户允许不止一个会话,那么它就会变得更加强大。要解决的难题是:“会话何时真正结束”?

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

前台会话服务通常是最简单的变体。例如,X-Windowdbus服务以图形登录启动和终止。但是,如果您开始打印大型 PDF,您肯定希望这项工作能够成功完成或干净地终止而不留下任何残渣,对吗?

这些类型的会话服务要么需要在后台继续运行,要么在服务意外终止后必须有某种方式进行清理。在我们的移动世界中,设备经常会终止。想想你的显示器。你可以随时插入和拔下显示器。无需重新启动计算机。但是,如果你拔下所有屏幕会发生什么?当然,X11 会终止。对于在 X11 会话中运行的某些用户服务来说,这种情况是意外发生的,可能是在较长时间运行的任务中。

这很/run/user/$UID/方便,因为最后一个用户会话结束后,此目录会被自动清除。因此,服务可以相信,用户将清除存储在 中的所有内容/run/user/$UID/

因此所有与会话相关的服务都应使用该目录。

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

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

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

把它们加起来:

如果您有一个设计合理的服务,那么您永远不需要普通的 PID 文件/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/

祝你今天过得愉快。

答案2

systemd.exec手册对其选项有如下说明RuntimeDirectory

接受目录名称列表。如果设置,则在单元启动时将在下面/run(用于系统服务)或下面$XDG_RUNTIME_DIR(用于用户服务)创建指定名称的一个或多个目录,并在单元停止时删除。

此外,在pam_systemd手册页,我们可以找到以下信息$XDG_RUNTIME_DIR(重点是我的):

与用户登录机器时绑定的用户私有用户可写目录的路径。它会在用户首次登录时自动创建,在用户最后一次注销时删除

使用这两个手册,我们可以推断出$XDG_RUNTIME_DIR/run/user/$UID在我的 Arch 安装中)不是系统服务的正确选择。相反,它们通常被放入/run(至少在 Arch 和 Gentoo 上)。也可以RuntimeDirectory按照上述方法在 中创建它们。

/var/run只不过是/run这些天的一个符号链接。

相关内容