getgrgid#
Look up a group record by numeric group ID.
getgrgid asks the system group database for the entry whose gid is
GID and returns what it finds. It is the numeric counterpart of
getgrnam and mirrors the C library call getgrgid(3).
In list context you get the unpacked record fields; in scalar context
you get the group name.
Synopsis#
my ($name, $passwd, $gid, $members) = getgrgid($gid);
my $name = getgrgid($gid);
What you get back#
In list context, four values unpacked from struct group:
# 0 1 2 3
my ( $name, $passwd, $gid, $members ) = getgrgid($gid);
$name— the group name.$passwd— the group password field. On modern systems this is typically"x"or empty; real hashes live in a shadow database.$gid— the numeric group ID (the same number you passed in, echoed back from the record).$members— a single space-separated string of member login names, not a list. Split it yourself when you need an array:my @users = split / /, (getgrgid($gid))[3];
In scalar context, just the group name:
my $name = getgrgid(0); # "root" on most Linux systems
If no group with the given GID exists, the function returns the empty
list in list context and undef in scalar context. A
system-level failure (e.g. NSS backend unreachable) is reported the
same way; check $! if you need to distinguish.
Global state it touches#
$!— set on system-level failure of the underlyinggetgrgid(3)call. Not set when theGIDsimply has no matching entry; that is a normal “not found”, not an error.The process-wide group-database iteration cursor maintained by libc.
getgrgiddoes not advance or reset the cursor used bygetgrent,setgrent, andendgrent, but it shares the same underlying file descriptor on most implementations — interleaving direct lookups with iteration is portable in theory and surprising in practice.
Examples#
Look up the primary group name for the current process:
my $group = getgrgid($(); # $( is the real GID
print "running as group: $group\n";
Resolve a file’s group ID to a name, with a sensible fallback for orphaned GIDs (files owned by a group that no longer exists):
my $gid = (stat $file)[5];
my $name = getgrgid($gid) // "<unknown gid $gid>";
Unpack the full record and list the members:
if (my ($name, undef, $gid, $members) = getgrgid(100)) {
my @users = split / /, $members;
print "group $name ($gid) has ", scalar(@users), " members\n";
}
Guard against the “no such group” case explicitly — the empty list in
boolean/list context is already falsy, so an if suffices:
unless (my @gr = getgrgid($gid)) {
die "no group with gid $gid\n";
}
Pair with getpwuid to render a directory listing’s owner
and group columns:
my @st = stat $path or die "stat $path: $!";
my $user = getpwuid($st[4]) // $st[4];
my $grp = getgrgid($st[5]) // $st[5];
printf "%-8s %-8s %s\n", $user, $grp, $path;
Edge cases#
Scalar vs list context matters.
getgrgid($gid)in scalar context yields only the group name; wrap in parentheses or assign to a list to get the full record:my $name = getgrgid(0); # "root" my @record = getgrgid(0); # four-element list my $gid_out = (getgrgid(0))[2]; # the gid field
$membersis a string, not an array. The whitespace-joined form is historical and matches perl5’spp_gpwent/pp_ggrentoutput. Splitting on/ /(single space) is the canonical idiom; splitting on/\s+/is slightly more forgiving if a backend ever uses tabs.Empty groups return
$membersas the empty string.split / /, ""yields the empty list, which is what callers usually want.Numeric coercion.
GIDis passed to the C call as an integer. A non-numeric scalar is coerced:"0root"becomes0. Pass a clean integer.GID namespace overlap. Multiple group entries with the same
gidare legal in/etc/groupand in NSS.getgrgidreturns one of them — which one is backend-defined. Do not rely on which name comes back when GIDs collide; usegetgrnamfor the reverse direction when the name matters.NSS / nsswitch.conf. The lookup follows the system’s name service switch —
files,sss,ldap, etc. A successful lookup in a test harness on one host may fail on another with a different NSS configuration. This is a property of the C library, not of Perl.Large groups. Very large group-member lists (hundreds of members) can arrive truncated if the backend’s internal buffer is smaller than the rendered line. This is a libc / NSS limitation; Perl faithfully surfaces whatever the system returned.
Threaded builds. On systems that provide
getgrgid_r, perl transparently calls the reentrant variant. Callers see no difference.Taint. Under
-T,$passwdand$memberscome back tainted — the first because it may encode credentials, the second because administrators can change it.$nameand$gidare not tainted.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
getgrnam— the inverse lookup: group record by name rather than bygidgetgrent— iterate every group entry when you need to scan rather than look upsetgrentandendgrent— reset and release the iteration cursor used bygetgrentgetpwuid— the passwd-side counterpart; pair withgetgrgidto render owner/group columnsUser::grent— by-name accessor object that overridesgetgrgidwhen you prefer$gr->nameover positional unpacking