正如所讨论的,该logname
实用程序不久前对许多用户来说变得无法使用,因为它依赖于出于安全考虑而被故意破坏的东西这里。当我阅读讨论时,该功能不太可能恢复。
我使用变通办法已经有一段时间了,但现在我觉得它们开始让我感到不舒服,所以我正在寻找一个合适的长期解决方案,我惊讶地发现,似乎没有太多解决方案。
提出了最常链接的解决方案这里,但它源自这里其中还存在一个提示,即通过环境变量提出的解决方案SUDO_USER
不可移植。
另一个建议的解决方案是创建一个包含用户名的文件并编写一个 bash 别名或类似的东西来模拟日志名功能,但我不会将其称为适当的替代方案,至少因为它假设了对环境的可控性,而这可能并不总是可能的,最好说,在至少的情况下。
解决方案who
来自这里很有趣,但我找不到任何有关是否存在相关可靠性或可移植性限制的信息。
除了这些方法之外,这个领域的空气很快就变得稀薄,所以我决定在这里提问,希望能得到一些关于这个话题和我到目前为止的想法的新意见。
答案1
TL,DR:您可能想要,即使它的行为并不总是匹配。但它并不是在所有发行版上都可以开箱即用。请注意,我的答案假设是 Linux,它不适用于其他 Unix 变体。/proc/PID/loginuid
logname
我认为您不会找到完全满意的答案,因为您对此没有明确的期望logname
。一方面,您当前正在使用logname
,它基于 utmp 记录 — 将用户与终端关联的记录,并且根据终端仿真器的意愿进行更新(许多终端仿真器不这样做)。另一方面,您期望“更改用户名的可能性应仅限于超级用户”。 utmp记录不是这样的!正如所解释的在您引用的评论线程中,utmp 记录在大多数情况下都有效,但它们可以被伪造。
定义“用于登录控制台的用户名”是有问题的。名义上的情况已经很清楚了,但是还有很多复杂的情况。如果用户呼叫su
并附加到另一个用户的屏幕会话,会发生什么情况?如果用户附加到另一个用户的 X11 或 VNC 会话,会发生什么情况?如何将进程跟踪到终端——对于没有控制终端的进程该怎么办?
实际上是Linux做有一个“登录UID”的概念。对于每个进程来说,它都是可见的。该信息由内核跟踪,但由用户态让内核知道登录何时发生。这通常是通过以下方式完成的/proc/PID/loginuid
pam_loginuid。在幕后,它是通过写入 来完成的/proc/self/loginuid
。 Linux 的登录 UID 遵循进程祖先,这并不总是正确的定义,但具有简单的优点。
请注意,如果进程的登录 UID 是 4294967295,则该进程可能会更改它。 Init 以登录 UID 4294967295 开头(等于 32 位值 -1);这通常表示不属于任何登录会话的进程。只要登录过程正确设置登录 UID(就在将真实 UID 从 root 设置为登录用户之前),就可以了。但是,如果有一种无需设置登录 UID 即可登录的方法,那么用户可以声明他们选择的任何登录 UID。因此,只有当系统上运行进程的所有方式都经过设置登录 UID 的步骤时,此信息才是可靠的 - 忘记一个步骤,信息就变得毫无用处。
实验上,在 Debian jessie 机器上,我所有登录 UID 为 -1 的长时间运行的进程都是系统服务。但是有一些方法可以运行登录 UID 为 -1 的进程,例如通过 incron。我不知道还有多少其他方式; incron 是我第一次尝试并且成功了。在Ubuntu 16.04机器上,pam_loginuid
lightdm的条目被注释掉了,我还没有调查原因。也许 Ubuntu 的 lightdm 和 incron 应该被视为安全错误,但事实是,今天您不能依赖主要发行版中开箱即用的登录 UID。
也可以看看Loginuid,是否应该允许更改(可变或不可变)?,这是关于防止 root 更改登录 UID 的内核选项。但要注意的是,只有在登录UID设置为合适的值后才有效;如果用户在登录 UID 仍设置为 -1 的情况下运行进程,那么他们可以将其设置为他们想要的任何值。事实上,让 init 切换到不同的值(例如 -2)并pam_loginuid
覆盖该值会更安全;那么 -1 永远不会发生,-2 表示“未知”。