Needing one command to run under a group you're not logged in as, without spawning a whole new shell, is exactly what sg is for. This walks through checking group membership, running that one command safely quoted, and confirming your original shell comes back unchanged. It uses sg from shadow-utils 4.13, installed here as the Ubuntu login package version 1:4.13+dfsg1-4ubuntu3.2.
Allow about ten minutes. You need an interactive shell, the sg command, and membership of a target group. The examples use the users group because it exists on this machine; replace it with a group your own account is allowed to use. No command in this guide needs sudo.
Confirm which executable will run and record the package version, both read-only checks:
$ command -v sg
/usr/bin/sg
$ dpkg-query -W -f='${Package} ${Version}\n' login
login 1:4.13+dfsg1-4ubuntu3.2
The local manual describes the syntax as sg [-] [group [-c] command]. The command runs via /bin/sh. The optional leading hyphen affects how the login environment is set up; leave it out unless you specifically need that behaviour.
Checkpoint: if command -v sg returns nothing, stop here and install it through your distribution's package manager. Do not copy a different sg implementation into a system directory.
List the groups available to your current account. This does not change account or group configuration:
$ id
uid=1000(alice) gid=1000(users) groups=1000(users),27(sudo),987(docker),1002(bob),1003(carol)
$ id -nG
users sudo docker bob carol
Pick an exact name from your own output. Group membership is not the same as permission to edit /etc/group, and sg cannot grant a group your account is not already allowed to use. Adding a user to a group is a separate administrative change and sits outside this workflow.
For a first test, set a shell variable to a group you can already see. Quoting the value makes the boundary clear:
$ TARGET_GROUP='users'
$ getent group "$TARGET_GROUP"
users:x:1000:alice
The member list in getent is not the whole permission model. What matters is that the group exists and your account is permitted to use it. Empty lookup? Fix the name before invoking sg at all.
Pass the group, then -c, then one quoted shell command. The quotes matter: without them, your current interactive shell can consume the command words before sg ever sees them.
$ sg "$TARGET_GROUP" -c 'id -g; id -gn'
1000
users
The first line is the numeric effective group ID, the second its name; your values will differ. A successful id -gn here verifies the effective group inside the child shell, rather than just showing the groups attached to the parent process.
Checkpoint: run a command with an unmistakable marker:
$ sg "$TARGET_GROUP" -c 'printf "effective group: "; id -gn; printf "sg-child-ok\n"'
effective group: users
sg-child-ok
The child shell exits after the command runs. Your original shell stays exactly where it was, and the group change does not outlive that child.
Everything inside the command string gets interpreted by /bin/sh. Use single quotes around a fixed command, and quote any data that may contain spaces or shell metacharacters. This asks the child shell to print a literal path alongside the group name:
$ sg "$TARGET_GROUP" -c 'printf "group=%s path=%s\n" "$(id -gn)" "/srv/shared files"'
group=users path=/srv/shared files
Warning: do not place untrusted text directly into the command string. A value containing ;, command substitution syntax or a newline can become an entirely different shell command. If a script needs to run user-supplied data, pass it as a positional argument to a carefully written script, or validate it before building the invocation.
When the command itself contains a single quote, reach for a small script file or a quoting strategy you have actually tested. Escaping one more layer of shell syntax by instinct is a reliable way to run the wrong command.
sg earns its keep by taking a command and handing control straight back to the parent shell once it ends. That's different from newgrp, which commonly replaces the current shell with a new group shell outright. You can see the boundary without touching your account:
$ printf 'parent group: '; id -gn
parent group: users
$ sg "$TARGET_GROUP" -c 'printf "child group: "; id -gn'
child group: users
$ printf 'after sg: '; id -gn
after sg: users
Test with a different group and the middle line should name that group, while the last line still shows the parent shell's original group. This is a process-scoped change, not a rewrite of your primary group.
Treat a misspelled or unavailable group as a configuration error. Reproduce the lookup first, without reaching for extra privileges:
$ getent group definitely-not-a-group
$ sg definitely-not-a-group -c 'id -gn'
sg: group 'definitely-not-a-group' does not exist
The exact diagnostic, and whether a password prompt appears, can vary with the local shadow-utils build and group configuration. A password prompt is not a reason to guess credentials: check the group name, membership and the local /etc/group and /etc/gshadow policy with the system administrator instead.
If a command works when run directly but fails under sg, inspect both the effective group and the command's own access check:
$ sg "$TARGET_GROUP" -c 'id; test -r /path/to/file && echo readable || echo not-readable'
uid=1000(alice) gid=1000(users) groups=1000(users)
readable
The group shown by id is only one part of access control. File mode bits, ACLs, parent-directory search permission, mounts, MAC policy and the child program's own checks can all affect the result. Do not fix an access failure by changing file ownership or permissions until you know which policy is actually blocking you.
Running sg changes the credentials used by the child command. It does not edit /etc/passwd, /etc/shadow, /etc/group or /etc/gshadow, and it does not change your primary group permanently. The shadow-utils manual notes that its activity can be logged when SYSLOG_SG_ENAB in /etc/login.defs is enabled, so do not assume the invocation is invisible on a managed system.
Warning: be especially careful with commands that write shared files, access devices or start services. The group can grant access the parent shell didn't have. Test with id, printf or a read-only check first. There is no general undo for a successful write performed by the child, so use a new destination and a backup before replacing anything valuable.
sg binary and shadow-utils package version.sg -c.sg exits.