Run a bare su TARGET_USER expecting a clean login and you can end up with your own working directory and a mixed environment instead. This guide covers a repeatable way to run a shell or one command as another Linux user, verify the effective identity, and avoid carrying the wrong environment across the privilege boundary. The examples target util-linux su 2.39.3, the version installed here in package util-linux 2.39.3-9ubuntu6.6.
Allow about ten minutes. You need a terminal, the target account's password unless your PAM policy grants an exception, and permission to run the command you choose. Most checks are ordinary, unprivileged commands. Changing to root or selecting groups is security-sensitive and requires the appropriate authority.
Confirm which implementation and version will handle the request. This is read-only:
$ command -v su
/usr/bin/su
$ su --version
su from util-linux 2.39.3
The command uses PAM for authentication, account checks and session management. Its local policy can therefore make a valid command fail, require a password, or restrict which accounts may be used. The files that matter include /etc/pam.d/su, /etc/pam.d/su-l, /etc/default/su when present, and /etc/login.defs. Inspecting them is useful when diagnosing a failure, but do not edit authentication policy as part of a routine test.
Checkpoint: write down the exact target account before you continue. Use getent passwd TARGET_USER to confirm the account exists and to see its home directory and configured shell.
For a one-off command, put --command before the target username. Replace TARGET_USER with a real account name; the shell receives the command string with its -c option:
$ su --command='id; printf "home=%s\npwd=%s\n" "$HOME" "$PWD"' TARGET_USER
Password:
uid=1001(TARGET_USER) gid=1001(TARGET_USER) groups=1001(TARGET_USER)
home=/home/TARGET_USER
pwd=/current/directory
The password prompt is expected when PAM requires authentication. The numeric IDs, group list and home path will differ on your machine. The useful result is that uid names the requested account and the command exits normally.
Do not paste an untrusted value directly into the command string. The string is interpreted by the target user's shell, so shell metacharacters and substitutions have their usual meaning. For a fixed, reviewed command such as id or pwd, the example is straightforward; for variable data, quote it for the shell and keep it separate from the command options.
The default mode does not change directory and only adjusts a small part of the environment, so you can be left with the caller's working directory and a mixture of caller and target settings. Use --login when the target account should receive a login-like session:
$ su --login --command='id; printf "home=%s\npwd=%s\nshell=%s\npath=%s\n" "$HOME" "$PWD" "$SHELL" "$PATH"' TARGET_USER
Password:
uid=1001(TARGET_USER) gid=1001(TARGET_USER) groups=1001(TARGET_USER)
home=/home/TARGET_USER
pwd=/home/TARGET_USER
shell=/bin/bash
path=/usr/local/bin:/usr/bin:/bin
Exact output depends on the account, /etc/login.defs, PAM modules and the host's merged-/usr layout. In this mode, su clears the environment apart from TERM and any permitted whitelist entries, sets HOME, SHELL, USER, LOGNAME and PATH, changes to the target home directory, and starts the shell as a login shell.
The single hyphen and -l are shortcuts for --login. Prefer the long spelling in scripts and notes because its purpose is obvious. Treat login mode as a boundary, not a cosmetic prompt change: startup files may run and commands may resolve from a different PATH.
Omit --command when you need to work interactively:
$ su --login TARGET_USER
Password:
TARGET_USER@host:~$ id -un
TARGET_USER
TARGET_USER@host:~$ exit
logout
$
The prompt is controlled by the target shell and may look different. Verify with id -un rather than trusting the prompt. Type exit or press Ctrl-D to return to the original shell. No persistent account or service state is changed by entering and leaving this shell, but commands run inside it can change files, processes and services according to the target user's permissions.
Security warning: su to root gives the child shell root privileges. Review every command before pressing Enter, especially commands involving recursive deletion, package changes, ownership, firewall rules or service restarts. If you only need one privileged action, prefer a reviewed one-off command and verify its target first.
--preserve-environment, also available as -p or -m, keeps the caller's environment instead of setting HOME, SHELL, USER and LOGNAME. It is ignored when --login is specified, which makes this combination misleading:
$ su --login --preserve-environment --command='printf "home=%s shell=%s\n" "$HOME" "$SHELL"' TARGET_USER
Choose one intent. Use --login for a clean target-user session, and --preserve-environment only when a specific inherited variable is required and you have checked its effect. Environment values influence configuration, search paths and sometimes credentials, so preserving them across users is a security-sensitive choice.
If login mode needs one harmless extra variable, --whitelist-environment=NAME can retain it while clearing the rest. It cannot preserve HOME, SHELL, USER, LOGNAME or PATH. Do not whitelist a secret merely to avoid re-entering it; pass credentials through the application's supported mechanism instead.
A successful command normally returns the child's status. Check it immediately if the result matters:
$ su --command='sh -c "exit 7"' TARGET_USER
Password:
$ printf 'su status: %s\n' "$?"
su status: 7
These values help distinguish authentication or setup trouble from a failure in the command itself. A password rejection, an account restriction or a locked shell is a PAM or account-policy problem. Check the spelling with getent passwd TARGET_USER, confirm the account is allowed to log in, and read the relevant system log according to your distribution's practice. Do not work around a policy failure by copying passwords into scripts.
--group=GROUP selects a primary group and --supp-group=GROUP adds a supplementary group. The installed manual restricts both options to root, and the first supplementary group becomes primary if no primary group is supplied. These options change authority, so use them only for a documented administrative need and verify the result with id:
# su --login --group=TARGET_GROUP --command='id' TARGET_USER
uid=1001(TARGET_USER) gid=1002(TARGET_GROUP) groups=1002(TARGET_GROUP),1001(TARGET_USER)
The leading # marks a root shell, not text to paste into a normal shell. If you are not already root, use your approved privilege mechanism to run this command. There is no undo command for a child process's group selection: exit it and start a new session without the option. Persistent group membership is managed in account configuration, not by this invocation.
The --shell=SHELL option selects the shell only when policy permits it. For a target account with a restricted shell not listed in /etc/shells, ordinary users cannot override that restriction with --shell or an inherited SHELL variable, though root can. Treat an unexpected shell as a policy signal, not an invitation to bypass it.
getent passwd and confirmed identity with id.exit.