su Command in Linux: Complete Guide to Switching Users, Superuser Access, and Parameters

su command in Linux and it perimeters

Before sudo became the default habit on most distributions, su was how everyone got root. I still use it constantly — mostly su - for a full login-shell switch, and su username when I need to genuinely become another account, not just run one privileged command. It’s a small tool, but the details around environment handling and PAM integration matter more than the short man page suggests. Here’s the complete rundown.

What su Does

su (substitute/switch user) changes the effective user ID and group ID of the current shell session to that of another account, prompting for that account’s password (unless you’re already root, in which case no password is required — root can su to anyone). Without an argument, it defaults to switching to root.

Syntax

Confirmed from su --help on util-linux 2.39.3:

Usage:
 su [options] [-] [<user> [<argument>...]]

Change the effective user ID and group ID to that of <user>.
A mere - implies -l.  If <user> is not given, root is assumed.

Full Option Reference

OptionLong formDescription
-, -l--loginStart a full login shell — resets environment, changes to the target user’s home directory, sources their shell profile
-c CMD--command=CMDRun a single command via the target user’s shell, then return
--session-command=CMDLike -c but without creating a new session
-m, -p--preserve-environmentKeep the current environment variables instead of resetting them
-w LIST--whitelist-environment=LISTPreserve only specific listed variables
-g GROUP--group=GROUPSpecify the primary group for the new shell
-G GROUP--supp-group=GROUPAdd a supplementary group
-s SHELL--shell=SHELLRun a specific shell, if listed in /etc/shells
-f--fastPass -f to csh/tcsh shells (skip startup file processing)
-P--ptyCreate a new pseudo-terminal for the session
-h--helpShow help
-V--versionShow version

The Critical Difference: su vs su –

This is the single most important thing to understand about su, and it’s the source of more confusion than any other aspect of the command.

su username     # switches UID/GID, but KEEPS your current shell environment
su - username   # full login shell: new environment, new $HOME, runs target's .bash_profile

Without the dash, your $PATH, $HOME, and other environment variables often remain those of the original user, which can cause genuinely confusing bugs — running a command that resolves to the wrong binary because $PATH still points at your original account’s directories, or a script writing to the wrong $HOME. I default to su - essentially always, specifically to avoid this class of problem, and I’d recommend the same unless you have a specific reason to preserve environment.

Tested Reference Behavior

$ su --help
Usage:
 su [options] [-] [<user> [<argument>...]]

Change the effective user ID and group ID to that of <user>.
A mere - implies -l.  If <user> is not given, root is assumed.

Options:
 -m, -p, --preserve-environment      do not reset environment variables
 -w, --whitelist-environment <list>  don't reset specified variables

 -g, --group <group>             specify the primary group
 -G, --supp-group <group>        specify a supplemental group

 -, -l, --login                  make the shell a login shell
 -c, --command <command>         pass a single command to the shell with -c
 --session-command <command>     pass a single command to the shell with -c
                                   and do not create a new session
 -f, --fast                      pass -f to the shell (for csh or tcsh)
 -s, --shell <shell>             run <shell> if /etc/shells allows it

 -h, --help                      display this help
 -V, --version                   display version

For more details see su(1).

Common Usage Patterns

Switch to root, full environment

su -

Switch to a specific user, full login environment

su - deploy

Run a single command as another user without an interactive shell

su -c "systemctl restart nginx" -

I use this pattern in scripts that need one privileged action embedded inside a larger workflow otherwise running as a normal user, without spawning a persistent shell.

Run a command as a specific non-root user (common in service scripts)

su -c "python manage.py migrate" deploy

Preserve your current environment while switching

su -m otheruser

Useful when you specifically need your own $PATH or environment variables (like a custom $http_proxy) to carry over into the new user’s shell — the opposite intent of su -.

How su Works Internally

su is a setuid-root binary — when you run it, it briefly runs with root privileges regardless of who invoked it, which is what lets it change the process’s UID/GID at all (an unprivileged process cannot normally change its own UID). This setuid mechanism is exactly why su‘s binary permissions and integrity matter so much from a security standpoint; it’s one of the small number of binaries on a typical system that’s a genuine privilege-escalation surface by design.

Authentication is handled through PAM (Pluggable Authentication Modules), configured in /etc/pam.d/su. This is why su‘s behavior can differ across distributions and hardened configurations — PAM modules control things like whether members of the wheel/sudo group can su to root without any restriction, whether failed attempts are logged or rate-limited (pam_tally2/pam_faillock), and whether su is restricted entirely to a specific group via pam_wheel.so.

A typical relevant line from /etc/pam.d/su:

auth       required   pam_wheel.so use_uid

Uncommenting this line restricts su (specifically to root) to members of the wheel group only — a common hardening step on security-conscious systems, and default behavior on many RHEL-family distributions.

Real-World Administration Examples

Restricting su to root to the wheel group (Debian/Ubuntu)

# Add user to the group allowed to su
usermod -aG sudo deploy   # sudo group also commonly doubles as this gate on Debian-family

# Enable the wheel/sudo restriction in PAM
echo 'auth required pam_wheel.so use_uid' >> /etc/pam.d/su

Running a service as its dedicated service account

su -s /bin/bash -c "npm start" -l appuser

Explicitly specifying -s here matters if the target account’s default shell in /etc/passwd is /usr/sbin/nologin (common for service accounts, blocking direct interactive login) — -s overrides that for this one command.

Auditing recent su activity

grep " su " /var/log/auth.log | tail -20     # Debian/Ubuntu
journalctl _COMM=su --since "1 hour ago"     # systemd-based systems

I check this regularly on shared systems as a basic accountability measure — knowing who switched to which account, and when.

Troubleshooting

“su: Authentication failure” — wrong password, or PAM configuration is blocking the account (e.g., pam_wheel.so restriction and the calling user isn’t in the required group).

“This account is currently not available” — the target user’s shell in /etc/passwd is set to /sbin/nologin or /bin/false; use -s /bin/bash to explicitly override for administrative access to a service account.

Environment looks wrong after switching (wrong PATH, wrong HOME) — you ran su user instead of su - user; always prefer the dash form unless you deliberately want to preserve environment with -m.

“su: must be run from a terminal” in certain restricted contexts — some PAM configurations or securetty restrictions block su to root from non-console terminals; check /etc/securetty if this applies to your setup (mostly relevant to direct root login restriction, less so to plain su).

su vs sudo vs Related Commands

CommandModel
suFull session switch to another user’s shell/environment; requires that user’s password (or none, if you’re already root)
sudoPer-command privilege elevation; requires the invoking user’s own password (by default), governed by fine-grained rules in /etc/sudoers
sudo -iFunctionally similar to su - but authenticated and audited through the sudo/PAM stack, with per-user logging
machinectl shell / runuserAlternative mechanisms for running a shell/command as another user, runuser specifically skips PAM’s su-specific authentication checks and is intended for use by already-privileged scripts, not interactive login
loginFull authentication and session setup from a fresh terminal, the mechanism su - mimics internally for the login-shell parts

I default to sudo for day-to-day single privileged commands specifically because it logs exactly what was run and by whom, without requiring the root password to be known or shared at all — a meaningfully better security posture on any multi-admin system. I reach for su - when I genuinely need an extended session as another account, not just one command.

Security Implications

su to root effectively requires either knowing the root password or already being root — which is precisely why many hardened distributions disable direct root login and password-based su to root entirely, funneling all privilege escalation through sudo with per-user auditing instead. If you administer a multi-user system, I’d strongly recommend:

  • Locking the root account’s password (passwd -l root) and relying exclusively on sudo
  • Restricting su via pam_wheel.so even if the root password remains usable, as defense in depth
  • Reviewing /var/log/auth.log or journalctl regularly for unexpected su attempts, successful or failed

Because su is setuid-root, any vulnerability in the binary itself is a serious local privilege-escalation risk — keep util-linux/shadow-utils (whichever package provides su on your distribution) patched promptly; this is core-system-package territory, not a low-priority update.

Distribution Compatibility

su is provided either by util-linux (Debian/Ubuntu) or shadow-utils (RHEL/Fedora), with essentially identical core behavior and flag sets across both. Default PAM restrictiveness differs meaningfully: RHEL-family distributions have historically shipped pam_wheel.so commented out by default (same as Debian), so out-of-the-box behavior tends to be similar, but hardened baseline images (CIS-benchmarked AMIs, for example) frequently enable the wheel restriction as part of their hardening profile. Always check /etc/pam.d/su on any system you’re newly administering rather than assuming defaults.

su in Scripts: Handling Arguments Correctly

A subtlety that catches people writing their first automation around su: everything after the target username is passed as arguments to the shell being invoked, not interpreted by su itself, which can produce confusing quoting issues if not handled carefully:

su -c "tar czf /backup/data.tar.gz /home/deploy/data" deploy

Here the entire quoted string is handed to deploy‘s shell as a single command via -c, exactly as if deploy had typed it interactively. Nesting quotes inside that string requires care — I generally prefer writing more complex operations into a standalone script file and invoking that via su -c /path/to/script.sh targetuser, rather than fighting escalating quote-escaping inside a one-liner, especially once variables need to be substituted from the calling context.

su Without a Password: The wheel Group Exception

One behavior worth calling out explicitly because it surprises people: if you’re already root, su - anyuser requires no password at all — root can become any account without authentication, by design, since root already has unrestricted access to the system regardless. This is different from a non-root user’s su attempt, which always requires the target account’s own password (subject to whatever PAM restrictions apply). This asymmetry is exactly why protecting root access itself — via SSH key-only login, disabling direct root SSH, and tightly controlling sudo/wheel membership — matters more than any individual su configuration detail; once an attacker has root, every other account on the system is trivially reachable through su alone.

Checking Who Last Used su

last | grep -i su
lastlog -u deploy

While su itself doesn’t create a traditional login record the way SSH sessions do, PAM’s session logging (through pam_unix or pam_systemd) typically records the switch in the system journal or /var/log/auth.log, and reviewing this periodically is a reasonable part of routine access auditing on any system where multiple administrators share elevated access.

Summary

su is a straightforward command with a subtle but critical detail — the dash — that determines whether you get a clean, correctly-scoped environment for the target user or a confusing hybrid of two accounts’ settings. Understanding that it’s PAM-driven and setuid-root explains both its flexibility (per-distribution authentication policy) and why it deserves the same security scrutiny you’d give any other privilege boundary on the system.

References

  • Linux man-pages — su(1): https://man7.org/linux/man-pages/man1/su.1.html
  • Linux-PAM System Administrators’ Guide: https://www.man7.org/linux/man-pages/man8/PAM.8.html
  • Red Hat Documentation — Configuring su access: https://access.redhat.com/documentation/
  • Debian Wiki — sudo vs su: https://wiki.debian.org/sudo
Total
0
Shares

Leave a Reply

Previous Post
passwd command in Linux and it perimeters

passwd Command in Linux: Complete Guide to Password Management and Parameters

Next Post
df command in Linux and it perimeters

df Command in Linux: Complete Guide to Disk Space Reporting and Parameters

Related Posts