我经常想获取与用户ID相关联的登录名,并且由于事实证明这是一种常见用例,因此我决定编写一个Shell函数来完成此操作。当我主要使用GNU / Linux发行版时,我尝试编写脚本以使其尽可能具有可移植性,并检查我在做什么与POSIX兼容。
解析 /etc/passwd
我尝试的第一种方法是解析/etc/passwd
(使用awk
)。
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
但是,这种方法的问题在于登录名可能不是本地的,例如,用户身份验证可以通过NIS或LDAP进行。
使用getent
命令
使用getent passwd
比解析更具可移植性,/etc/passwd
因为它还会查询非本地NIS或LDAP数据库。
getent passwd "$uid" | cut -d: -f1
不幸的是,该getent
实用程序似乎未由POSIX指定。
使用id
命令
id
是POSIX标准化的实用程序,用于获取有关用户身份的数据。
BSD和GNU实现接受用户ID作为操作数:
这意味着它可用于打印与用户ID关联的登录名:
id -nu "$uid"
但是,未在POSIX中指定提供用户ID作为操作数。它仅描述使用登录名作为操作数。
结合以上所有
我考虑过将以上三种方法合并为以下内容:
get_username(){
uid="$1"
# First try using getent
getent passwd "$uid" | cut -d: -f1 ||
# Next try using the UID as an operand to id.
id -nu "$uid" ||
# As a last resort, parse `/etc/passwd`.
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
}
但是,这是笨拙,不雅且更重要的是不可靠。如果用户ID无效或不存在,它将以非零状态退出。在编写一个更长而笨拙的shell脚本来分析并存储每个命令调用的退出状态之前,我想我会在这里问:
是否有一种更优雅,更便携(与POSIX兼容)的方式来获取与用户ID相关联的登录名?
getent
也id
不会返回任何值。找到所有用户的唯一方法是枚举所有用户,如果用户数据库允许的话。(/etc/passwd
显然,正在寻找那里定义的用户的作品。)
/etc/passwd
并/etc/shadow
测试了这种情况,并验证了两者的行为,id
并getent passwd
按照您的描述进行操作。如果在某个阶段最终使用了一个用户有多个名称的系统,则将与这些系统实用程序相同,并且将第一个出现的名称视为该用户的规范名称。
setuid(some_id)
,并且没有任何要求some_id
可以包含在任何用户数据库中。对于Linux上的用户名称空间之类的东西,这可能会成为脚本的一个残酷假设。