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