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