谁设置 $USER 和 $USERNAME 环境变量?

谁设置 $USER 和 $USERNAME 环境变量?

另外,这些变量是否始终与当前登录的用户名匹配(在我的 Debian 系统上是这样)?我可以假设它们在其他 Unix(类似)系统中可用吗?

我也很好奇为什么人们会使用whoami而不是仅仅读取这些变量中的任何一个。

答案1

它是登录

Linux登录(1)手册页说:

的价值$HOME,$用户,$壳牌,$路径,$日志名, 和 $邮件根据密码条目中的相应字段进行设置。

自由BSD登录(1)手册页说:

登录实用程序将信息输入到环境中(参见 环境(7)) 指定用户的主目录 (HOME)、命令解释器 (SHELL)、搜索路径 (PATH)、终端类型 (TERM) 和用户名(LOGNAME 和 USER)。

网络BSD,开放BSD操作系统手册页也说了同样的事情。

这是源代码从 util-linux 登录:

setenv("HOME", pwd->pw_dir, 0); /* legal to override */
setenv("USER", pwd->pw_name, 1);
setenv("SHELL", pwd->pw_shell, 1);
/* ... */
setenv("LOGNAME", pwd->pw_name, 1);

这是源代码从 FreeBSD 登录:

(void)setenv("LOGNAME", username, 1);
(void)setenv("USER", username, 1);
(void)setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0);

答案2

没有规则。有些贝壳喜欢tcshzsh设置$LOGNAMEzsh设置$USERNAME(如果允许的话,您甚至可以为变量分配一个值,以将 uids/gids 更改为该用户的 uids/gids)。

它可能是由一些让您登录的东西设置的,例如(在终端上登录时login调用,有时由其他东西调用,例如)、、、、、、、图形登录管理器,也可能不是。gettyin.rlogindcronsusudosshdrshd

如果有登录,根据我的经验,$USER通常会设置(但在该登录会话中更改用户 ID(通过 setuid 命令)后可能不会更新。POSIX 要求$LOGNAME在登录时设置(和cron)。

要可移植地获取登录名,最好是使用该logname命令(如果没有任何登录,它可能不会返回任何内容)。要获取用户 ID,请使用id -u.获取当前有效用户id对应的用户名:id -un.要获取所有这些信息(大多数情况下,每个用户 ID 只有一个用户名,但这并不能保证):

perl -le 'while ($n = getpwent()) {print $n if getpwnam($n) == $>}'

尽管这可能不适用于无法枚举用户数据库的系统(例如有时会在网络用户数据库中发生这种情况)。

答案3

您可能想要依赖POSIX这里是标准的,因为在某个时间点,您可能不仅关心用户登录(由程序管理login),还关心cron作业等。

因此,您应该知道 POSIX 需要$LOGNAME但不需要$USER.例如,$USER可能不会由 cron 设置,正如在基思·汤普森的回答,其中还引用了一些关于这与 System-V 与 BSD 的历史有何关系的历史:

...至少在我的系统(Ubuntu 14.04)上,$USER 环境变量没有为 cron 作业设置。相反,您可以使用 $LOGNAME,它是 cron 作业环境的一部分。

根据环境(7)手册页(键入 man environ 来阅读),$USER 由 BSD 派生程序使用,$LOGNAME 由 System-V 派生程序使用。

答案4

如果您想使用环境变量(而不是whoamiorgetpwentgetpwnam)并且不确定它们是否在所有 *NIX 系统上始终以相同的方式设置,请在 bash 中尝试以下操作:

THIS_USER=${USER:-${USERNAME:-${LOGNAME}}}
echo ${THIS_USER}

如果它仍然是空的,那么你就处于一个相当深奥的系统中。 ;)

相关内容