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


34

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

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


2
查看man页面,whoami报告与您的有效用户ID关联的名称。这意味着如果您正在使用sudo或运行setuid可执行文件,它将返回不同的结果。如果已sudo设置,请尝试sudo whoami例如。
约瑟夫·R。13年

4
USER并且USERNAME是普通的环境变量,这意味着,如果需要,可以将它们设置为任意值。只需键入USER=xyz。换句话说,即使这些变量存在,也不能保证它们的值与当前登录的用户名匹配。
Uwe

@Uwe By guarantee,我的意思是默认情况下(即假设用户未更改它们)。
tshepang

2
@Tshepang作为我的第一个评论的跟进:比较sudo whoamisudo echo $USER
Joseph R.

2
@JosephR。为此sudo echo $USER,外壳展开$USER然后调用sudo。因此,当然不会产生与相同的输出whoami。像sudo whoamisudo sh -c 'echo $USER'(通常)输出root。关于您对whoami使用EUID的评论,请注意即使使用UID sudo whoami也会输出。集两者 EUID和UID为它运行(除极不寻常的情况,你明确地将其配置为以其他方式表现)的命令。比较到。rootwhoamisudosudo id -usudo id -ru
伊利亚·卡根

Answers:


29

它是登录名

Linux login(1)手册页显示:

对于价值$ HOME$ USER$ SHELL$ PATH$ LOGNAME$ MAIL根据在密码输入相应的字段设置。

FreeBSD login(1)手册页显示:

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

NetBSD的OpenBSD系统OS X的手册页说同样的话。

这是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
在我的Fedora 16框上,同时具有USERUSERNAMEset,并且您的命令仅返回LOGNAME
约瑟夫·R。13年

1
@JosephR。,很不幸,我手上没有Fedora,但我也研究了FreeBSD的资源,请参阅
UPD。– poige

但这显然不是Fedora的情况。我要说的是,login设置这些变量似乎并不是唯一的事情。
约瑟夫·R。13年

1
请注意,Linux只是一个内核,它没有login命令。使用Linux作为其内核的OS可以自由使用他们喜欢的任何实现。例如,基于Debian的系统倾向于使用shadow-utils中的系统,而不是util-linux中的系统。
斯特凡Chazelas

1
请注意,通过大多数图形登录管理器登录或由大多数图形登录管理器登录login时,通常不会调用该功能ssh
斯特凡Chazelas

11

没有规则 一些贝壳喜欢tcshzsh镶嵌$LOGNAMEzsh$USER

它可以通过一些事情,您登录等进行设定login(如通过调用getty一个终端上登录时,有时用相同的其他的事情in.rlogind), ,cronsusudosshdrshd图形登录管理或可能没有。

但是,根据我的经验,如果已登录$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。如Keith Thompson$USER回答中所指出的,例如cron可能未设置cg还引用了一些有关它与System-V vs BSD历史的关系的历史:

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

根据environ(7)手册页(键入man environ进行读取),$ USER由BSD派生程序使用,而$ LOGNAME由System-V派生程序使用。


1

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

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

如果毕竟还是空的,那么您就处于一个比较深奥的系统上。;)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.