Read Linux Group Memberships with groups
You will use groups to inspect the groups attached to your current process or to look up one or more named users. You will also check the command version, capture an exit status, and avoid treating a group listing as proof that a running process has already gained a new permission. Allow about ten minutes. The examples use GNU coreutils 9.4, installed here as package version 9.4-3ubuntu6.3.
The route
Jump straight to the step you need, or tick off Done means at the end.
This is a read-only workflow. It does not add users to groups, reload a session, change file ownership or alter a service. You normally do not need sudo.
1. Check the installed command
Start by confirming which executable the shell will run and which package supplied it:
$ command -v groups
/usr/bin/groups
$ groups --version
groups (GNU coreutils) 9.4
$ dpkg-query -W -f='\${Package} \${Version}\n' coreutils
coreutils 9.4-3ubuntu6.3
The exact path and package revision can differ on another distribution. The installed manual page documents the behaviour used here. It accepts optional usernames and documents only --help and --version as options.
2. Inspect the current process
With no username, groups prints the memberships for the current process:
$ groups
dixon sudo docker andy owendixon direktor
Your output will contain your own username's groups. The command prints a space-separated list without a label. That makes it convenient at a prompt, but less self-describing in a log.
Checkpoint: save the result without changing anything, then count the fields if you need a quick sanity check:
$ current_groups=$(groups)
$ printf '%s\n' "$current_groups"
dixon sudo docker andy owendixon direktor
$ printf 'group count: %s\n' "$(wc -w <<< "$current_groups")"
group count: 6
Do not use the count as an authorisation decision. Group names can be added or removed in the account database while a process continues to use credentials inherited when it started.
3. Look up a named user
Pass a username to see the groups recorded for that account. This is useful when checking a service account, an administrator's account or a proposed file-access change:
$ groups root
root : root kvm ollama
$ groups nobody
nobody : nogroup
For a named user, the output includes the username followed by a colon. The lookup is not a test of the groups belonging to your shell. It asks the system's group database about the account you named.
You can supply several usernames in one invocation:
$ groups root nobody
root : root kvm ollama
nobody : nogroup
Each requested account gets its own line. Keep the names explicit in scripts so a typo does not silently turn a check into one for a different account.
4. Distinguish account data from live credentials
The manual warns that the no-argument result is for the current process and may differ if the groups database has changed. This distinction matters after an administrator adds a user to a group.
First, inspect the account database:
$ groups YOUR_USER
YOUR_USER : YOUR_PRIMARY_GROUP YOUR_ADDITIONAL_GROUP
Replace YOUR_USER with a real account name. This does not update an already running shell. A new login session, or a deliberate credential refresh using your distribution's normal session tools, may be needed before a program receives the new supplementary group.
To check a particular process rather than relying on a shell's state, inspect its status record:
$ grep '^Groups:' /proc/$$/status
Groups: 27 100 999
The values in /proc/<pid>/status are numeric group IDs, while groups normally prints names. They are different views of process credentials. If a permission check is failing, compare the running process with the account lookup before changing file modes or restarting services.
5. Use the exit status in a script
A successful lookup returns status 0. An unknown username returns a non-zero status and a diagnostic:
$ groups definitely-not-a-real-user >/tmp/groups-missing.out 2>/tmp/groups-missing.err
$ printf 'exit status: %s\n' "$?"
exit status: 1
The quotation marks in the diagnostic depend on the locale. Scripts should test the status, not parse the message or assume that a particular group appears in the output.
if groups "$USER" >/tmp/groups-check.out 2>/tmp/groups-check.err; then
printf '%s\n' 'user lookup succeeded'
else
status=$?
printf 'groups lookup failed with status %s\n' "$status" >&2
exit "$status"
fi
The example uses the current account name supplied by the shell. If you substitute an external value, validate it as an account name before passing it to a command. Do not let untrusted text become a new option or a shell fragment.
The temporary files in these examples are ordinary state changes, even though they are harmless output capture. Remove them when they are no longer needed:
$ rm -f /tmp/groups-check.out /tmp/groups-check.err /tmp/groups-missing.out /tmp/groups-missing.err
Do not use a shared predictable path in a privileged script. If a root-owned service needs this check, use a private temporary directory and review its file handling. The normal interactive examples do not require elevation.
6. Keep permission changes separate
groups only reports information. It cannot add a user to a group, remove a membership or make a process reload credentials. Those actions belong to account-management and session-management tools and can change who may read files, access devices or administer services.
If you have just changed membership, do not immediately assume a failed access test proves the change was wrong. Check the account with groups USERNAME, then start a fresh session or restart only the relevant process using your normal operational procedure. Before restarting a service, confirm its unit, maintenance window and rollback path. A service restart can interrupt users even though the groups command itself is safe.
Use groups --help when you need the local synopsis. Use getent group GROUPNAME when you need the members recorded for one group rather than the groups associated with one user. These answer related but different questions.
Done means
- You confirmed the executable and installed GNU coreutils version.
- You used no username for the current process, and a username for an account-database lookup.
- You know that a changed group database does not automatically refresh existing process credentials.
- Your script checks the exit status and does not parse translated diagnostic text.
- You kept group-management and service-restart actions outside this read-only check.