How to list all users in a Linux group?

后端 未结 20 1167
春和景丽
春和景丽 2020-12-07 06:51

How do I list all members of a group in Linux (and possibly other unices)?

相关标签:
20条回答
  • 2020-12-07 07:37

    In UNIX (as opposed to GNU/Linux), there's the listusers command. See the Solaris man page for listusers.

    Note that this command is part of the open-source Heirloom Project. I assume that it's missing from GNU/Linux because RMS doesn't believe in groups and permissions. :-)

    0 讨论(0)
  • 2020-12-07 07:38

    Zed's implementation should probably be expanded to work on some of the other major UNIX.

    Someone have access to Solaris or HP-UX hardware?; did not test those cases.

    #!/usr/bin/perl
    #
    # Lists members of all groups, or optionally just the group
    # specified on the command line
    #
    # Date:         12/30/2013
    # Author:       William H. McCloskey, Jr.
    # Changes:      Added logic to detect host type & tailor subset of getent (OSX)
    # Attribution:
    #   The logic for this script was directly lifted from Zed Pobre's work.
    #     See below for Copyright notice.
    #   The idea to use dscl to emulate a subset of the now defunct getent on OSX
    #     came from
    #       http://zzamboni.org/\
    #         brt/2008/01/21/how-to-emulate-unix-getent-with-macosxs-dscl/
    #     with an example implementation lifted from
    #       https://github.com/petere/getent-osx/blob/master/getent
    #
    # Copyright © 2010-2013 by Zed Pobre (zed@debian.org or zed@resonant.org)
    #
    # Permission to use, copy, modify, and/or distribute this software for any
    # purpose with or without fee is hereby granted, provided that the above
    # copyright notice and this permission notice appear in all copies.
    #
    
    use strict; use warnings;
    
    $ENV{"PATH"} = "/usr/bin:/bin";
    
    # Only run on supported $os:
    my $os;
    ($os)=(`uname -a` =~ /^([\w-]+)/);
    unless ($os =~ /(HU-UX|SunOS|Linux|Darwin)/)
        {die "\$getent or equiv. does not exist:  Cannot run on $os\n";}
    
    my $wantedgroup = shift;
    
    my %groupmembers;
    
    my @users;
    
    # Acquire the list of @users based on what is available on this OS:
    if ($os =~ /(SunOS|Linux|HP-UX)/) {
        #HP-UX & Solaris assumed to be like Linux; they have not been tested.
        my $usertext = `getent passwd`;
        @users = $usertext =~ /^([a-zA-Z0-9_-]+):/gm;
    };
    if ($os =~ /Darwin/) {
        @users = `dscl . -ls /Users`;
        chop @users;
    }
    
    # Now just do what Zed did - thanks Zed.
    foreach my $userid (@users)
    {
        my $usergrouptext = `id -Gn $userid`;
        my @grouplist = split(' ',$usergrouptext);
    
        foreach my $group (@grouplist)
        {
            $groupmembers{$group}->{$userid} = 1;
        }
    }
    
    if($wantedgroup)
    {
        print_group_members($wantedgroup);
    }
    else
    {
        foreach my $group (sort keys %groupmembers)
        {
            print "Group ",$group," has the following members:\n";
            print_group_members($group);
            print "\n";
        }
    }
    
    sub print_group_members
    {
        my ($group) = @_;
        return unless $group;
    
        foreach my $member (sort keys %{$groupmembers{$group}})
        {
            print $member,"\n";
        }
    }
    

    If there is a better way to share this suggestion, please let me know; I considered many ways, and this is what I came up with.

    0 讨论(0)
  • 2020-12-07 07:39
    getent group <groupname>;
    

    It is portable across both Linux and Solaris, and it works with local group/password files, NIS, and LDAP configurations.

    0 讨论(0)
  • 2020-12-07 07:40

    I've done this similar to the perl code above, but replaced getent and id with native perl functions. It is much faster and should work across different *nix flavors.

    #!/usr/bin/env perl
    
    use strict;
    my $arg=shift;
    my %groupMembers; # defining outside of function so that hash is only built once for multiple function calls
    
    sub expandGroupMembers{
    my $groupQuery=shift;
    unless (%groupMembers){
        while (my($name,$pass,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire)=getpwent()) {
                my $primaryGroup=getgrgid($gid);
                $groupMembers{$primaryGroup}->{$name}=1;
        }
        while (my($gname,$gpasswd,$gid,$members)=getgrent()) {
                foreach my $member (split / /, $members){
                        $groupMembers{$gname}->{$member}=1;
                }
        }
    }
    my $membersConcat=join(",",sort keys %{$groupMembers{$groupQuery}});
    return "$membersConcat" || "$groupQuery Does have any members";
    }
    print &expandGroupMembers($arg)."\n";
    
    0 讨论(0)
  • 2020-12-07 07:41

    Here's a very simple awk script that takes into account all common pitfalls listed in the other answers:

    getent passwd | awk -F: -v group_name="wheel" '
      BEGIN {
        "getent group " group_name | getline groupline;
        if (!groupline) exit 1;
        split(groupline, groupdef, ":");
        guid = groupdef[3];
        split(groupdef[4], users, ",");
        for (k in users) print users[k]
      }
      $4 == guid {print $1}'
    

    I'm using this with my ldap-enabled setup, runs on anything with standards-compliant getent & awk, including solaris 8+ and hpux.

    0 讨论(0)
  • 2020-12-07 07:42

    Unfortunately, there is no good, portable way to do this that I know of. If you attempt to parse /etc/group, as others are suggesting, you will miss users who have that group as their primary group and anyone who has been added to that group via a mechanism other than UNIX flat files (i.e. LDAP, NIS, pam-pgsql, etc.).

    If I absolutely had to do this myself, I'd probably do it in reverse: use id to get the groups of every user on the system (which will pull all sources visible to NSS), and use Perl or something similar to maintain a hash table for each group discovered noting the membership of that user.

    Edit: Of course, this leaves you with a similar problem: how to get a list of every user on the system. Since my location uses only flat files and LDAP, I can just get a list from both locations, but that may or may not be true for your environment.

    Edit 2: Someone in passing reminded me that getent passwd will return a list of all users on the system including ones from LDAP/NIS/etc., but getent group still will still miss users that are members only via the default group entry, so that inspired me to write this quick hack.

    
    #!/usr/bin/perl -T
    #
    # Lists members of all groups, or optionally just the group
    # specified on the command line
    #
    # Copyright © 2010-2013 by Zed Pobre (zed@debian.org or zed@resonant.org)
    #
    # Permission to use, copy, modify, and/or distribute this software for any
    # purpose with or without fee is hereby granted, provided that the above
    # copyright notice and this permission notice appear in all copies.
    #
    
    use strict; use warnings;
    
    $ENV{"PATH"} = "/usr/bin:/bin";
    
    my $wantedgroup = shift;
    
    my %groupmembers;
    my $usertext = `getent passwd`;
    
    my @users = $usertext =~ /^([a-zA-Z0-9_-]+):/gm;
    
    foreach my $userid (@users)
    {
        my $usergrouptext = `id -Gn $userid`;
        my @grouplist = split(' ',$usergrouptext);
    
        foreach my $group (@grouplist)
        {
            $groupmembers{$group}->{$userid} = 1;
        }
    }
    
    if($wantedgroup)
    {
        print_group_members($wantedgroup);
    }
    else
    {
        foreach my $group (sort keys %groupmembers)
        {
            print "Group ",$group," has the following members:\n";
            print_group_members($group);
            print "\n";
        }
    }
    
    sub print_group_members
    {
        my ($group) = @_;
        return unless $group;
    
        foreach my $member (sort keys %{$groupmembers{$group}})
        {
            print $member,"\n";
        }
    }
    
    0 讨论(0)
提交回复
热议问题