我可以通过 /etc/passwd 进行 grep,但这看起来很繁重。 未安装“finger”,我想避免这种依赖性。 这是一个程序,所以如果有一些命令可以让您访问用户信息那就太好了。
您没有指定编程语言,所以我假设您想使用 shell;这是 Posix shell 的答案。
有两个步骤:获取适当的记录,然后从该记录中获取所需的字段。
首先,获取账户记录是通过查询
passwd
表来完成的:
$ user_name=foo
$ user_record="$(getent passwd $user_name)"
$ echo "$user_record"
foo:x:1023:1025:Fred Nurk,,,:/home/foo:/bin/bash
对于歇斯底里的葡萄干,用户的全名记录在一个名为 “GECOS”字段的字段中;使事情变得复杂的是,该字段通常有自己的结构,其全名只是几个可选子字段之一。因此,任何想要从帐户记录中获取全名的东西都需要解析这两个级别。
$ user_record="$(getent passwd $user_name)"
$ user_gecos_field="$(echo "$user_record" | cut -d ':' -f 5)"
$ user_full_name="$(echo "$user_gecos_field" | cut -d ',' -f 1)"
$ echo "$user_full_name"
Fred Nurk
您的编程语言可能有一个库函数可以用更少的步骤完成此操作。在 C 中,您可以使用“getpwnam”函数,然后解析 GECOS 字段。
在现代 glibc 系统上,使用以下命令:
getent passwd "username" | cut -d ':' -f 5
这将为您提供指定用户的
passwd
条目,独立于底层 NSS 模块。
阅读 getent
如果您已经在编程,则可以使用
getpwnam()
C 函数:
struct passwd *getpwnam(const char *name);
passwd
结构有一个pw_gecos
成员,其中应包含用户的全名。
阅读 getpwnam()
请注意,许多系统不仅仅使用此字段来表示用户的全名。最常见的约定是在字段中使用逗号 (
,
) 作为分隔符,并将用户的真实姓名放在前面。
其他答案的组合,在最小的 Debian/Ubuntu 安装上进行了测试:
getent passwd "$USER" | cut -d ':' -f 5 | cut -d ',' -f 1
万一您想从 C 语言执行此操作,请尝试以下操作:
#include <sys/types.h>
#include <pwd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
/* Get full name of a user, given their username. Return 0 for not found,
-1 for error, or 1 for success. Copy name to `fullname`, but only up
to max-1 chars (max includes trailing '\0'). Note that if the GECOS
field contains commas, only up to to (but not including) the first comma
is copied, since the commas are a convention to add more than just the
name into the field, e.g., room number, phone number, etc. */
static int getfullname(const char *username, char *fullname, size_t max)
{
struct passwd *p;
size_t n;
errno = 0;
p = getpwnam(username);
if (p == NULL && errno == 0)
return 0;
if (p == NULL)
return -1;
if (max == 0)
return 1;
n = strcspn(p->pw_gecos, ",");
if (n > max - 1)
n = max - 1;
memcpy(fullname, p->pw_gecos, n);
fullname[n] = '\0';
return 1;
}
int main(int argc, char **argv)
{
int i;
int ret;
char fullname[1024];
for (i = 1; i < argc; ++i) {
ret = getfullname(argv[i], fullname, sizeof fullname);
if (ret == -1)
printf("ERROR: %s: %s\n", argv[i], strerror(errno));
else if (ret == 0)
printf("UNKONWN: %s\n", argv[i]);
else
printf("%s: %s\n", argv[i], fullname);
}
return 0;
}
试试这个:
getent passwd eutl420 | awk -F':' '{gsub(",", "",$5); print $5}'
前两个答案可以合并为一行:
getent passwd <username> | cut -d ':' -f 5 | cut -d ',' -f 1
我的代码可以在 bash 和 ksh 中运行,但不能在 dash 或旧的 Bourne shell 中运行。它也会读取其他字段,以防您需要它们。
IFS=: read user x uid gid gecos hm sh < <( getent passwd $USER )
name=${gecos%%,*}
echo "$name"
您还可以扫描整个 /etc/passwd 文件。这在普通的 Bourne shell 中可以在 1 个进程中工作,但对于 LDAP 或其他什么则不然。
while IFS=: read user x uid gid gecos hm sh; do
name=${gecos%%,*}
[ $uid -ge 1000 -a $uid -lt 60000 ] && echo "$name"
done < /etc/passwd
另一方面,使用工具是好的。 C也不错。
我在 Linux 上想到的将全名放入变量的方法是:
u_id=`id -u`
uname=`awk -F: -vid=$u_id '{if ($3 == id) print $5}' /etc/passwd`
然后只需简单地使用变量,例如:
$ echo $uname
古老的手指也可能有帮助:-)
finger $USER |head -n1 |cut -d : -f3
取1:
$ user_name=sshd
$ awk -F: "\$1 == \"$user_name\" { print \$5 }" /etc/passwd
Secure Shell Daemon
但是,passwd 数据库支持 gecos 中的特殊字符“&”,应将其替换为用户名的大写值:
$ user_name=operator
$ awk -F: "\$1 == \"$user_name\" { print \$5 }" /etc/passwd
System &
这里的大多数答案(手指解决方案除外)都不尊重&。 如果你想支持这个案例,那么你需要一个更复杂的脚本。
服用2:
$ user_name=operator
$ awk -F: "\$1 == \"$user_name\" { u=\$1; sub(/./, toupper(substr(u,1,1)), u);
gsub(/&/, u, \$5); print \$5 }" /etc/passwd
System Operator