私は、学生全員がアカウントを持つ大学の 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
getent
Linux システムには、標準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()
、ログイン システムの構成方法 (、LDAP、NIS、…?) について何らかの仮定をする必要がなく/etc/passwd
、システムが実際の構成で情報を取得するだけでよいという大きな利点があります。
編集:passwd
データベースのストレージ バックエンド (例: LDAP) がデータベースの列挙を許可せず (したがって)、キーによって明示的に要求されたデータ セット (例: ログイン名または UID、したがってまたは が機能する可能性があります)getpwent()
のみを渡す場合があります。この場合 (および対象のユーザー名が非常に適切に命名されているため)、@masegaloeh のスクリプトを変更して手動で「列挙」することもできます。getpwuid()
getpwnam()
#!/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からすべてのユーザー情報を取得できます