How to List All Users in a Linux Group

How to list all users in a Linux group?

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";
}
}

List all the users logged in a specific group

In the general case, this is a painful exercise. I've seen password and group files in production use that defy logic — but work.

For sake of concrete example, let's suppose you're interested in the logged-in members of the group student.

Now, the entry in the group database (/etc/group file, plus network resources) for a named group such as student may or may not have any members listed. That doesn't necessarily mean there are no members in the group, though. Each entry in the password database (/etc/passwd file, plus network resources) has a group number assigned, and the group number might be the same as the group number for group student, in which case that user belongs to the group too.

However, we're not done yet. Suppose the entry in the group database reads:

student:x:2971:newton,einstein,socrates,plato

There might be other entries in the group database such as:

student_2020:x:2971:able,cain,adam,eve

Because this entry uses the same group number as group student, anyone who is listed in the student_2020 entry is functionally a member of group student — the o/s kernel uses the number, not the name, to determine groups.

There can be sound reasons for splitting up group file entries; historically at least, some programs ran into problems if the list of names is too long. That's bad programming, but when it is the system-provided software that does the crashing, you avoid triggering the crash. Hence the multiple entries.

You can end up with multiple entries with different group numbers for the same group name (really confusing!) or with multiple names for the same group number (as above) or with multiple entries with the same group number and name. It can be hit'n'miss as to what gets reported for any given name or number.

You can run into analogous problems in password files. For example, multiple user names all with the same user number is sometimes used to allow multiple people root access (their user number is 0) but each has a separate password so some tracking is feasible. However, it is generally better to use sudo these days — it was not always available, though. Occasionally, there'll be a mistake and the same user name will appear twice with different user numbers. Normally, the first entry in the file is used, but it can be confusing (at best).

However, it is not clear which programs you can use to analyze these issues, or derive a definitive answer about what is what. If you search for the group by name (getgrnam() in C), then you typically get the first entry that matches that name (but it isn't necessarily clear whether that entry came from the network or the local file system). If you search for the group by number (getgrgid() in C), then you typically get the first entry that matches that number. However, if you scan the entire database with setgrent() plus repeated getgrent() plus endgrent() (optional), you might see all sorts of entries.

As a case in point, I can run this code on my Mac:

#include <grp.h>
#include <stdio.h>

int main(void)
{
struct group *grp;
while ((grp = getgrent()) != 0)
{
printf("%5d %-15s", grp->gr_gid, grp->gr_name);
char **mem = grp->gr_mem;
char *pad = " -- ";
while (*mem != 0)
{
printf("%s%s", pad, *mem++);
pad = ", ";
}
putchar('\n');
}
return(0);
}

When I do that and pipe the output through sort -n, I get (in parts):

   -2 nobody         
-2 nobody
-1 nogroup
-1 nogroup
0 wheel -- root
0 wheel -- root
1 daemon -- root
1 daemon -- root
2 kmem -- root
2 kmem -- root
3 sys -- root
3 sys -- root
4 tty -- root
4 tty -- root
5 operator -- root
5 operator -- root
6 mail -- _teamsserver
6 mail -- _teamsserver
7 bin
7 bin

16 group
16 group
20 staff -- root
20 staff -- root, informix, anonymous, supernumerary
24 _networkd
24 _networkd

Why the double entries? Well, there's a file /etc/group which contains one set of entries — for example:

staff:*:20:root

There is also a database, Open Directory, that is consulted. Indeed, the first lines of the /etc/group file on a Mac are comment lines (comments are not usually supported on other o/s) that read:

##
# Group Database
#
# Note that this file is consulted directly only when the system is running
# in single-user mode. At other times this information is provided by
# Open Directory.
#
# See the opendirectoryd(8) man page for additional information about
# Open Directory.
##

There's a similar spiel at the top of the /etc/passwd file. The Open Directory entry for staff lists 3 additional users. What's curious is that when I run id, I'm also in group staff:

uid=501(jleffler) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),204(_developer),399(com.apple.access_ssh),701(com.apple.sharepoint.group.1),100(_lpoperator),702(com.apple.sharepoint.group.2)

My name isn't even listed in /etc/passwd; it only appears in the Open Directory portion of the database.

And my name is only listed explicitly against groups 204 and 399 in the groups database; it is given group 20 in the password database; I'm not sure how groups 12, 61, 100, 701, 702 are associated with my user ID. (And it is news to me that I don't know this — sometimes answering a question is educational for more people than the one who asked the question.)

So, as I noted at the start, it is not straight-forward to find the answer to your question.

If you scan the password database and groups database, you can get a reasonable approximation to the information you need, but you may never get the full answer unless you explore the controls on your platform.

The answer by Abhishek Keshhri suggests there is a (Linux-specific? — not on macOS, anyway) command getent that can be used to analyze the group database (and probably the user or password database, and maybe others too). There are Open Directory tools on macOS to analyze the password and group databases on macOS. You don't have to write and compile C code (but the code shown isn't rocket science).

how to display users under a group in a line for each user in Linux bash

I suggest using sed instead of grep

sed -n -e 's/^visitors\:x\:1011\://p' /etc/group | tr ',' '\n'

UPD: detailed explain of sed part is here. tr examples you can find here

Is there a command to list all Unix group names?

To list all local groups which have users assigned to them, use this command:

cut -d: -f1 /etc/group | sort

For more info- >
Unix groups,
Cut command,
sort command

Python script to list users and groups

For *nix, you have the pwd and grp modules. You iterate through pwd.getpwall() to get all users. You look up their group names with grp.getgrgid(gid).

import pwd, grp
for p in pwd.getpwall():
print p[0], grp.getgrgid(p[3])[0]

In Linux / Unix, is there a way to list every group ownership that appears under a specific folder path?

Assuming GNU find:

find /path/to/MyFolder -printf "%g\n" | sort | uniq -c

will show all distinct groups owning files in the directory tree, and how many files each group owns.



Related Topics



Leave a reply



Submit