另外,这些变量是否始终与当前登录的用户名匹配(在我的 Debian 系统上是这样)?我可以假设它们在其他 Unix(类似)系统中可用吗?
我也很好奇为什么人们会使用whoami
而不是仅仅读取这些变量中的任何一个。
答案1
它是登录。
Linux登录(1)手册页说:
的价值$HOME,$用户,$壳牌,$路径,$日志名, 和 $邮件根据密码条目中的相应字段进行设置。
自由BSD登录(1)手册页说:
这登录实用程序将信息输入到环境中(参见 环境(7)) 指定用户的主目录 (HOME)、命令解释器 (SHELL)、搜索路径 (PATH)、终端类型 (TERM) 和用户名(LOGNAME 和 USER)。
这是源代码从 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
没有规则。有些贝壳喜欢tcsh
或zsh
设置$LOGNAME
。zsh
设置$USERNAME
(如果允许的话,您甚至可以为变量分配一个值,以将 uids/gids 更改为该用户的 uids/gids)。
它可能是由一些让您登录的东西设置的,例如(在终端上登录时login
调用,有时由其他东西调用,例如)、、、、、、、图形登录管理器,也可能不是。getty
in.rlogind
cron
su
sudo
sshd
rshd
如果有登录,根据我的经验,$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
如果您想使用环境变量(而不是whoami
orgetpwent
和getpwnam
)并且不确定它们是否在所有 *NIX 系统上始终以相同的方式设置,请在 bash 中尝试以下操作:
THIS_USER=${USER:-${USERNAME:-${LOGNAME}}}
echo ${THIS_USER}
如果它仍然是空的,那么你就处于一个相当深奥的系统中。 ;)