我可以访问一所大学的 Linux 服务器,所有学生都有帐户。我可以通过键入 来检索他们的全名finger username
,并通过键入 来检索他们的部门id username
。所有学生的用户名都是连续的。例如:
e205846
e205847
e205848
e205849
e205850
...
我是否可以编写某种脚本并将所有信息检索到某种数据库中?或者已经有可用的工具吗?另外,作为旁注,Linux 中有一些 www 文件夹,其中包含所有用户名。
这是一个例子
e147290@beluga:~$ finger e204158
Login: e204158 Name: april oneil
Directory: /home705/e204158 Shell: /bin/bash
Never logged in.
No mail.
No Plan.
e147290@beluga:~$ id e204159
uid=53653(e204158) gid=5621(ce_bs) groups=5621(ce_bs)
答案1
在 Linux 系统上有一个getent
程序,它利用标准get*ent(2)
函数(getpwent()
就是这里使用的函数)。你要检索的是数据库的内容passwd
(尝试man nsswitch.conf
进一步理解):
$ getent passwd
root:x:0:0:root:/root:/bin/bash
sashroot:x:0:0:root:/root:/bin/sash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:65004:65534:sync:/bin:/bin/sync
games:x:65005:65060:games:/usr/games:/bin/sh
man:x:65006:65012:man:/var/cache/man:/bin/sh
lp:x:65007:7:lp:/var/spool/lpd:/bin/sh
mail:x:65008:65008:mail:/var/mail:/bin/sh
...
标准系统帐户滚动后,它变得更加有趣。
如果您不是 Linux 系统,则可以通过使用该函数自行编写转储用户数据库的内容来轻松实现这一点getpwent(2)
。 C 语言的一个例子是这样的:
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
int
main(void)
{
struct passwd *pwd;
while ((pwd = getpwent()) != NULL) {
printf("user = `%s', uid = %d, gid = %d, name = `%s'\n",
pwd->pw_name, pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos);
}
return 0;
}
将其放入文件中test.c
并使用以下命令构建它
$ gcc -o test test.c
然后你可以打电话./test
看看你得到了什么:
$ ./test
user = `root', uid = 0, gid = 0, name = `root'
user = `sashroot', uid = 0, gid = 0, name = `root'
user = `daemon', uid = 1, gid = 1, name = `daemon'
user = `bin', uid = 2, gid = 2, name = `bin'
user = `sys', uid = 3, gid = 3, name = `sys'
user = `sync', uid = 65004, gid = 65534, name = `sync'
user = `games', uid = 65005, gid = 65060, name = `games'
user = `man', uid = 65006, gid = 65012, name = `man'
user = `lp', uid = 65007, gid = 7, name = `lp'
user = `mail', uid = 65008, gid = 65008, name = `mail'
...
如上所述,稍后会变得更有趣。
使用这种方法getwent()
有一个很大的优点,即您不必对登录系统的配置方式(/etc/passwd
LDAP、NIS,……?)做出任何假设,而只需让系统根据其实际配置检索信息。
编辑:可能会发生这样的情况:passwd
数据库的存储后端(例如 LDAP)不允许枚举数据库(因此getpwent()
),而只向您提供密钥明确请求的数据集(例如登录名或 UID,因此getpwuid()
或getpwnam()
可能有效)。在这种情况下(并且由于您的目标用户名的命名如此整齐),您仍然可以通过修改 @masegaloeh 的脚本来手动“枚举”:
#!/bin/bash
for i in {000000..999999}; do
getent passwd "e${i}" 2> /dev/null
done
如何在没有getent
系统 API ( getpwnam()
、getpwuid()
) 的情况下执行此操作留给读者作为练习。
答案2
getent 确实是在 Unix/Linux 系统上通过名称开关访问任何数据库的正确方法,因此无论帐户是否本地存储在 /etc/passwd 中,或者它们是否在 LDAP、AD、NIS 或您在 nsswitch.conf 中配置的任何服务。
所以我会这样做:
getent passwd | awk -F: '$1 ~"^e[0-9]*$" {print $5}'
这将打印所有以“e”开头且仅后跟数字的帐户的完整用户名。
如果我需要在 Windows 系统上执行此操作,我会安装 cygwin,然后按照上面的方法执行此操作:)。事实上,我刚刚在 Windows/cygwin 上测试了 getent,它运行得很好(有点令人惊讶)。
答案3
这个 bash 脚本将为你做循环
#!/bin/bash
for i in {205846..205850}; do
finger e${i}
id e${i}
done
您只需修改 205846 和 205850 即可获得不同的范围
答案4
您可以从/etc/passwd获取所有用户信息