getgrnam#
Look up a Unix group by name and return its /etc/group record.
getgrnam wraps the C library’s getgrnam(3). Given a group name like "wheel" or "staff", it returns the matching record from the system’s group database - the name, the encrypted password placeholder, the numeric GID, and the list of member login names. Use it when you have a group name in hand and need the GID or the membership list; use getgrgid for the inverse lookup.
Synopsis#
my ($name, $passwd, $gid, $members) = getgrnam NAME
my $gid = getgrnam NAME
What you get back#
List context yields a four-element list:
my ($name, $passwd, $gid, $members) = getgrnam "wheel";
Index | Field | Meaning |
|---|---|---|
0 |
| canonical group name (same as |
1 |
| group password field, typically |
2 |
| numeric group ID |
3 |
| space-separated string of member login names |
$members is a single scalar, not an array. Split it yourself when you want a list:
my @logins = split /\s+/, (getgrnam("wheel"))[3];
Scalar context yields the numeric GID (the “other thing”, since the lookup was by name):
my $gid = getgrnam "wheel";
No such group: list context returns the empty list; scalar context returns undef. Test scalar returns for definedness rather than truth - GID 0 (root) is a valid hit that is also false:
defined(my $gid = getgrnam $group) or die "no group '$group'";
Global state it touches#
None directly. getgrnam is a stateless lookup - unlike getgrent, it does not advance the group-database iterator, and setgrent / endgrent do not affect it. It does, however, share the underlying C library’s static result buffer with other getgr* calls on platforms without thread-safe variants; copy the fields you care about before calling another getgr* function.
Examples#
Resolve a group name to its GID:
my $gid = getgrnam "wheel";
defined $gid or die "no 'wheel' group on this system";
print "wheel GID = $gid\n";
List the members of a group:
my @fields = getgrnam "staff"
or die "no 'staff' group";
my @members = split /\s+/, $fields[3];
print "staff has ", scalar(@members), " members: @members\n";
Use a group name to set the effective GID (requires privilege):
my $gid = getgrnam "video"
// die "no 'video' group";
$) = "$gid $gid"; # effective + supplementary
Check whether a user is listed as a group member. Note that the primary group (the user’s GID in /etc/passwd) is not in $members - check both:
sub in_group {
my ($user, $group) = @_;
my @g = getgrnam $group or return 0;
return 1 if grep { $_ eq $user } split /\s+/, $g[3];
my @u = getpwnam $user or return 0;
return $u[3] == $g[2]; # primary group match
}
Object-oriented form via User::grent, which overrides the built-in with a by-name record:
use User::grent;
my $g = getgrnam "wheel";
printf "wheel: gid=%d members=%s\n", $g->gid, "@{$g->members}";
Edge cases#
Missing group: list context returns
(), scalar returnsundef. A bareif (getgrnam $g)is fine in list context but wrong in scalar context when the GID could be0:if (defined(my $gid = getgrnam $g)) { ... } # correct if (my $gid = getgrnam $g) { ... } # wrong for GID 0
Members is a string, not a list. Forgetting this and writing
scalar @members = getgrnam $g(or indexing$members[0]) silently gives wrong results. Alwayssplit /\s+/the fourth field.Primary-group members are absent from the list. A user whose
/etc/passwdGID matches the group is a member in the kernel’s eyes but will not appear in$members. Lookups that classify users by group must consultgetpwnamtoo.Password field is not a password. On every modern Linux the second field is
"x"(shadow redirection) or empty. It is never the plaintext or hash of a group password. Do not rely on its format.Case sensitivity: group names are case-sensitive on Linux.
getgrnam "Wheel"does not findwheel.Name with embedded whitespace or colon: the group database format does not allow either, so such names cannot exist; the lookup simply fails.
NSS backends: on systems configured with LDAP, SSSD, or other name-service switch modules,
getgrnamconsults those as well as/etc/group. Results therefore depend on/etc/nsswitch.confand the configured backends, not on/etc/groupalone.Taint: the fields come from outside the program, so under
-Tthey are tainted and must be laundered before use in sensitive operations.Thread safety: pperl automatically substitutes the thread-safe
getgrnam_rwhen the platform provides it. On platforms without it, concurrentgetgr*calls across threads can clobber each other’s results.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
getgrgid- inverse lookup by numeric GID; reach for this when you have the GID and want the group name or member listgetgrent- iterate every group in the database when you do not know the name or GID in advancesetgrent- rewind thegetgrentiterator to the start of the group databaseendgrent- close the group-database file descriptor opened by iterationgetpwnam- the parallel call for the user database; use alongsidegetgrnamwhen you need to resolve a user’s primary groupUser::grent- object-oriented wrapper that overridesgetgrnamto return a record object with named accessors (name,passwd,gid,members) instead of a positional list