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
How to Setup Oracle Odbc Drivers on Rhel 6/Linux
Check If Local Git Repo Is Ahead/Behind Remote
Undefined Reference to 'Clock_Gettime' Although '-Lrt' Is Given
Pipe Output to Use as the Search Specification for Grep on Linux
How to Run Dos2Unix on an Entire Directory
Use Grep to Find Content in Files and Move Them If They Match
How Is the Microsecond Time of Linux Gettimeofday() Obtained and What Is Its Accuracy
How to Transfer the Data of Columns to Rows (With Awk)
Execute Sudo Command on Linux from Plink.Exe on Windows
Windows Authentication Headers Without .Net. Possible
Linux Command to Empty All Files of a Directory
Bluetoothctl to Hcitool Equivalent Commands
Sighup for Reloading Configuration
How to Create a File in Linux from Terminal Window
When to Use Kernel Threads VS Workqueues in the Linux Kernel
What's the Accepted Method for Deploying a Linux Application That Relies on Shared Libraries