1

すべてのユーザーとそのユーザーが属する各グループを一覧表示しようとしてgrep /etc/passwdいます。/etc/group

IE:

Jon Doe, root:randomgroup:randomgroup2:randomgroup3
Billy Bob, admin:apache:backups
Timmy Tim, root:www

とにかく、これは私がこれまでに持っているものですが、grepグループにそれを取得してユーザーフィールドで一致させる方法が完全にはわかりません。

cat /etc/passwd | cut -d: -f1,5

これは、「:」とフルネームを持つユーザーのみを表示します

どうすればこれを行うことができますか?

4

4 に答える 4

6

grepを使用する要件が難しいものではない場合は/etc/passwd/etc/group次の解決策を検討してください。

for user in $(getent passwd | cut -d: -f1); do
    printf "%s: %s\n" $user "$(id -nG $user)"
done

この問題は見た目ほど単純ではないので、@JonathanLefflerのアドバイスに注意してください。

于 2012-09-21T23:37:54.053 に答える
4

ファイルのネットワークデータベースの可能性を無視しても、grep少なくとも、完全に実行する場合を除いて、このジョブに使用することはできません。おそらく、PerlまたはPython、あるいは選択した他の同様のスクリプト言語を使用する必要があります。

ファイルには、ユーザーの番号で指定されたグループが1つあることに注意してください/etc/passwd/etc/group同じユーザーに対して、任意の数の他のグループがリストされている可能性があります。ユーザーの「プライマリGID」が23インチであるとします/etc/passwd。のグループ23のエントリに/etc/groupそのユーザーがリストされるという保証はありません。

グループファイルにあらゆる種類の奇妙なものを表示させることができることに注意してください。

  • 同じGIDの複数の名前。
  • GID値が異なる同じグループ名の複数行。
  • にリストされているGID値は、にリストされ/etc/passwdていません/etc/group
  • ファイル内の同じUIDを持つ複数の名前/etc/passwd(多くの場合、異なるユーザーが自分の資格情報(名前とパスワード)でログインできるようにしますが、すべてUID 0、別名として実行されますroot)。

これらすべてに対処することは悪夢です—そしてそうです、これらのほとんどすべては私が作業しているシステムで発生しますが、管理していません。

どこかに、この分析に役立つコードがあります。これはPerlであり、およびを使用getpwent()getgrent()て情報を取得します(管理者が構成したファイルまたはネットワークから)。かわいくないです。


教室での運動分析には、おそらく次のものが必要です。

差出人/etc/passwd

  • ユーザー名
  • ユーザーID(UID)
  • プライマリグループID(GID)

差出人/etc/group

  • プライマリGIDの名前。
  • ユーザー名をリストする他のすべてのグループエントリ。

単にダックしてidコマンドを使用してほとんどの作業を行うと、はるかに簡単になります。でトロールして/etc/passwdユーザーgrep名を取得し、を使用idしてユーザーが属するグループを指定します。正常なシステムには十分である可能性が高い回答については、gvalkovによる回答を参照してください。

grep -o '^[^:]*' /etc/passwd |
xargs -L1 id

これにより、名前と番号がわかります。要件に合わせてオプションを微調整しますid。これはGNUを使用していますgrep。この-oオプションは便利ですが、移植性はありません。幸い、Unixユーザー名には改行(またはコロン)は含まれていません。これにより、の使用が簡単になりますxargs


ユーザーグループマップ

243行またはPerl、その一部はコメントしています。シバンラインを見てください。コードは3年前のものであり#!/usr/bin/env perl、これが作成されてから使用しています。次にuse warnings;、コード本体の上部にあります。

#!/bin/perl -w
#
# @(#)$Id: usergroupmap.pl,v 1.6 2009/06/08 02:30:19 jleffler Exp $
#
# Create a map of groups associated with users

use strict;
use constant debug => 0;

$| = 1;

my $group_entries = 0;  # Number of rows returned by getgrent()
my %usr_hash = ();      # List of lists of GID values keyed by user name
my %gid_hash = ();      # List of GID values count definitions
my %grp_hash = ();      # List of group name values and corresponding GID value
my %grp_count = ();     # List of count of entries with given group name
my %gid_name  = ();     # List of first occurring name for group, indexed by GID

{
    while (my ($name, $password, $gid, $userlist) = getgrent())
    {
        print "# $gid ($name) $userlist\n" if debug > 1;
        $group_entries++                                            ;# if debug > 0;
        $grp_hash{$name}  = $gid  unless defined $grp_hash{$name}   ;# if debug > 0;
        $grp_count{$name} = 0     unless defined $grp_count{$name}  ;# if debug > 0;
        $grp_count{$name}++                                         ;# if debug > 0;
        $gid_hash{$gid}   = 0     unless defined $grp_hash{$gid}    ;# if debug > 0;
        $gid_hash{$gid}++                                           ;# if debug > 0;
        $gid_name{$gid}   = $name unless defined $gid_name{$gid};

        foreach my $user (split /[, ]/, $userlist)
        {
            print ". $user\n" if debug > 1;
            $usr_hash{$user} = { } unless defined $usr_hash{$user};
            $usr_hash{$user}->{$gid} = 1;
        }
        printf "-- Group %-8s reappears with GID %5d (previously %5d)\n",
               $name, $gid, $grp_hash{$name} if $grp_hash{$name} != $gid;
        printf "-- GID   %-8d reappears with name %-8s (previously %-8s)\n",
               $gid, $name, $gid_name{$gid} if $name ne $gid_name{$gid};
    }
}

printf "Number of group entries: %5d\n", $group_entries         ;# if debug > 0;
printf "Number of group   names: %5d\n", scalar(keys %grp_hash) ;# if debug > 0;
printf "Number of group numbers: %5d\n", scalar(keys %gid_hash) ;# if debug > 0;
printf "Number of user    names: %5d\n", scalar(keys %usr_hash) ;# if debug > 0;

{
    foreach my $gid (sort keys %gid_hash)
    {
        printf "    Group ID %5d (%-8s) appears %2d times\n",
               $gid, $gid_name{$gid}, $gid_hash{$gid} if $gid_hash{$gid} > 1;
    }
}

# Nominally, this should print nothing.
# However, when the local /etc/group file and the NIS+ group file disagree, it does.
foreach my $name (sort keys %grp_count)
{
    printf "    Group name %-8s (%-5d) appears %2d times\n",
        $name, $grp_hash{$name}, $grp_count{$name} if $grp_count{$name} > 1;
}

# Determining canonical name for a group turns out to be tricky!
# On Solaris, it appears that:
# --- When groups are listed in /etc/group, the first name for a given GID is used
# -1-   Add to /etc/group:
#       a123::54876:username
#       a12::54876:username
#       a1::54876:username
#       a::54876:username
# ---   With these entries present, first one listed in /etc/group is 'name of group'
# ---   Demonstrated with multiple permutations of 4 entries.
#
# --- When groups are listed via NIS+, the shortest name for a given GID is used
# -1-   In NIS+ data,
#       -- GID   1360     reappears with name rand8    (previously rand4   )
#       -- GID   1360     reappears with name rand3    (previously rand4   )
#       -- GID   1360     reappears with name rand     (previously rand4   )
#       -- GID   1360     reappears with name rand9    (previously rand4   )
#       -- GID   1360     reappears with name rand1    (previously rand4   )
#       -- GID   1360     reappears with name rand2    (previously rand4   )
#       -- GID   1360     reappears with name rand10   (previously rand4   )
#       -- GID   1360     reappears with name rand5    (previously rand4   )
#       -- GID   1360     reappears with name rand7    (previously rand4   )
#       -- GID   1360     reappears with name rand11   (previously rand4   )
#       -- GID   1360     reappears with name rand12   (previously rand4   )
#       -- GID   1360     reappears with name rand6    (previously rand4   )
# ---   With these entries present, shortest name (rand) is listed by 'ls'.
# -2-   In NIS+ data,
#       -- GID   1240     reappears with name pd       (previously rd      )
# ---   With these entries present, first name with shortest length (rd) is listed by 'ls'.
# -3-   In NIS+ data,
#       -- GID   8714     reappears with name vcs-vsnet (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs  (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-tech (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-tech1 (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-sys2 (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-mgr1 (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-other (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-sys1 (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-mgr (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-mgr3 (previously vcs-mgr2)
#       -- GID   8714     reappears with name vcs-sys (previously vcs-mgr2)
# ---   With these entries present, shortest name (vcs) is listed by 'ls'.
# ---   Could be first name without punctuation?
# -4-   In NIS+ data + /etc/group data (other::1:root in /etc/group)
#       -- Group other    reappears with GID    20 (previously     1)
# ---   With these entries present, 'chgrp  1 x; ls -l x' lists group as other.
# ---   With these entries present, 'chgrp 20 x; ls -l x' lists group as other.
# ---   Hence, 'ls' must use getgrgid() to determine group name.
# -5-   In NIS+ data
#       -- GID   7777     reappears with name xgrp      (previously pdxgrp  )
# ---   With these entries present, 'chgrp pdxgrp x; ls -l x' lists xgrp as group.
# ---   Hence, as expected, chgrp uses getgrnam() to determine GID, and ls uses getgrgid().
# -6-   Add entry 'ccc::8714:' to /etc/group.
#       With this entry present, 'chgrp 8714 x; ls -l x' lists ccc as group.
# NB: /etc/nsswitch.conf lists 'group: files nis' (and 'passwd: files').
#
# ---   NB: No definitive test with same group name listed in both /etc/group and NIS+.
# ---   NB: No definitive info on why rand.
# ---   NB: No definitive info on why vcs.
# Hence: most reliable way to determine canonical name for a given GID is via getgrgid().
# Determining it from the results of getgrent() is unreliable.

my $max_groups = 0;
my $max_user = "";
my $tot_usrgrp = 0;
my %grp_lists = ();
foreach my $user (sort keys %usr_hash)
{
    my $groups = $usr_hash{$user};
    my $numgrps = scalar(keys %{$groups});
    $tot_usrgrp += $numgrps;
    if ($numgrps > $max_groups)
    {
        $max_groups = $numgrps;
        $max_user = $user;
    }
    my $grplst = "";
    foreach my $group (sort keys %{$groups})
    {
        $grplst .= " $group";
    }
    $grp_lists{$grplst} = 1;
    print "$user: $grplst\n" if debug;
}
printf "Maximum number of groups for one user (%s): %5d\n", $max_user, $max_groups;
printf "Total number of groups listed for all users: %5d\n", $tot_usrgrp;
printf "Total number of distinct group lists: %5d\n", scalar(keys %grp_lists);

my %name_hash = (); # List of distinct names - group names and user names
foreach my $user (keys %usr_hash)
{
    $name_hash{$user} = 1;
}
foreach my $group (keys %grp_hash)
{
    $name_hash{$group} = 1;
}

my $name_offset = 0;
foreach my $name (keys %name_hash)
{
    $name_hash{$name} = $name_offset;
    $name_offset += length($name) + 1;
}
printf "Total space needed for names = %5d\n", $name_offset;

# Add gid to group list if not already present
# If input is sorted, add condition: last if $grpnum > $gid;
sub add_gid
{
    my($gid, @groups) = @_;
    foreach my $grpnum (@groups)
    {
        return(@groups) if ($grpnum == $gid);
    }
    return sort { $a <=> $b } $gid, @groups;
}

# Get group set for given user name
sub getgrsetnam
{
    my($user) = @_;
    my(@groups) = ();
    my($usrref) = $usr_hash{$user};
    print "getgrsetnam(): name = $user\n" if debug > 0;
    push(@groups, sort { $a <=> $b } keys %$usrref) if defined $usrref;
    print "getgrsetnam(): groups = @groups\n" if debug > 0;
    my($name, $pass, $pw_uid, $gid) = getpwnam($user);
    # Not all users listed in groups appear in password
    if (defined $name)
    {
        print "getgrsetnam(): user = $name, $pw_uid, $gid\n" if debug > 0;
        @groups = add_gid($gid, @groups);
    }
    return(@groups);
}

# Get set of group IDs for given user number
sub getgrsetuid
{
    my($uid) = @_;
    print "getgrsetuid(): $uid\n" if debug > 0;
    my($name, $pass, $pw_uid, $gid) = getpwuid($uid);
    print "getgrsetuid(): $name, $pw_uid, $gid\n" if debug > 0;
    my(@groups) = ();
    # Not all UID values have a user name
    if (defined $name)
    {
        print "getgrsetuid(): name = $name\n" if debug > 0;
        @groups = getgrsetnam($name);
        @groups = add_gid($gid, @groups);
    }
    return(@groups);
}

{
    foreach my $user (sort keys %usr_hash)
    {
        print "user = $user\n" if debug > 0;
        my(@groups) = getgrsetnam($user);
        printf "%-9s @groups\n", "$user:";
    }
}

{
    foreach my $uid (0..65535)
    {
        my($name, $pass, $pw_uid, $gid) = getpwuid($uid);
        if (defined $name)
        {
            print "uid = $uid\n" if debug > 0;
            my(@groups) = getgrsetuid($uid);
            printf "%-9s (uid = %6d) @groups\n", "$name:", $uid;
        }
    }
}

__END__

要約出力の一部:

...
-- Group nobody   reappears with GID 60001 (previously    99)
...
Number of group entries:   225
Number of group   names:   221
Number of group numbers:   148
Number of user    names:  1072
    Group name xxxxxxx1 (297  ) appears  2 times
    Group name xxxxxxx2 (296  ) appears  2 times
    Group name xxxxxxx3 (102  ) appears  2 times
    Group name nobody   (99   ) appears  2 times
Maximum number of groups for one user (xxxxxxxx):    32
Total number of groups listed for all users:  2275
Total number of distinct group lists:   108
Total space needed for names =  9562

xの文字列は、私がマスクした別個の名前です。

于 2012-09-21T23:22:59.130 に答える
2

私は今日それを自分で必要としていて、manページをいじって約2分で次のことを思いついた。

for i in $(cat /etc/passwd | awk --field-separator=":" '{print $1}'); do id $i; done

次の方法でわずかに短縮することもできます。

for i in $(cat /etc/passwd | cut -d: -f1); do id $i; done

出力は、連続したいくつかのidコマンドのように見えます。

uid=34(backup) gid=34(backup) groups=34(backup)
uid=1000(bobby) gid=1000(bobby) groups=1000(bobby),27(sudo)
...

結果は最も読みやすいものではありませんが、非常にシンプルで覚えやすいものです。@gvalkovの答えは、その点ではるかに明確です。

于 2014-07-04T14:48:13.390 に答える
1

私はawkコマンドを使用して同じ問題を通過しました、私はほとんど同じように見える上記のいくつかの応答を見ました awk -F ":" '{print $value_of_field_to_print}' /path_of_file_containing_fields

たとえば、複数のフィールドが必要な場合は、別の印刷$value_of_field_to_printを追加し、それらの間にセパレータを追加します

これは次のようになります

awk -F ":" '{print $value_of_field_to_print print "separator" print 
$value_of_field_to_print2}' /path_of_file_containing_fields`

awkはファイルを処理するコマンドの名前であり、この-F fsオプションは入力フィールドの区切り文字「:」または「separator」を正規表現として定義しますfs。これにより、関数の使用を回避し、cat最終的に時間を節約できます。

于 2019-01-24T12:40:18.953 に答える