The Problem: Locked-Down Service Accounts
I have server-only users for things like CI, media streaming, or cron jobs. For security, I’ve removed shell access from /etc/passwd—they can’t log in interactively, but they can still own files and run processes.
Problem: sometimes you need to test something or debug an issue as that user. Traditionally, you’d temporarily edit /etc/passwd, change their shell back to /bin/bash, switch to them, test, then set it back. That’s annoying and error-prone.
Here’s the nuclear option: just override the shell with su -s and skip the whole dance.
The Basics: What is su?
su stands for “switch user.” It’s one of those foundational Unix tools that’s been around since the dawn of time—simple, powerful, dangerous if you’re not careful.
su usernameThis tries to switch to username. If successful, you’ll be that user (assuming permissions allow). You’ll be prompted for a password—they need to know it.
To become root:
su rootsu - # shorthand for "switch to root"The Difference: - (Login Shell) vs No Flag
Here’s where it gets subtle. There’s a big difference between su username and su - username.
Without -:
su usernameYou become username, but your environment is mostly the same as before. Your current working directory stays the same. Your $PATH, $HOME variables, and other shell config don’t get reloaded. You’re inheriting the parent shell’s environment.
With - (login shell):
su - usernamesu -l username # --login, same thingThis is a true login. It reads the target user’s .profile or .bashrc. Your working directory changes to their home. Environment variables are set up fresh, as if you’d logged in normally.
Use su - when you want the user’s full environment. Use plain su when you’re just borrowing their permissions temporarily.
The Real Power: -s (Custom Shell)
Now the magic:
su -s /bin/bash usernameThe -s flag lets you override the shell specified in /etc/passwd. Doesn’t matter if the account has /nologin or /bin/false—you get bash anyway.
Why is this useful?
- Service accounts with no shell. You need to debug that Jenkins user, but their shell is
/nologin. One command, no editing passwd, done. - Accounts with weird shells. Maybe someone left the shell set to
/bin/cshor/bin/ksh, and you want bash. - Consistent environment. You’re forcing bash even if the account normally uses something else.
You can combine flags:
su -s /bin/bash - username # login shell overridesu -s /bin/sh username # just sh, keep current envWhen You’d Actually Use This
Scenario 1: CI system user is broken
# CI user has /nologin, but you need to test a build manuallysu -s /bin/bash - jenkins# Now you're running as `jenkins`, with bash, in their home dirScenario 2: Debugging a cron job
# mediaserver user runs an encoding script, it's failing# You need to test it as the mediaserver usersu -s /bin/bash - mediaservercd /opt/encodingbash ./transcode.sh # run it exactly as the cron job doesScenario 3: Testing file permissions
# A script is supposed to work as user `appuser`, but you're not sure about permssu -s /bin/bash - appuserls -la /var/app/data/cat config.json # can they read it?su vs sudo su: When to Use Each
You might see sudo su or sudo -s floating around. What’s the difference?
su root or su -:
- Asks for root’s password
- Works offline (no auth daemon needed)
- Direct switch to root
- Simple, old-school
sudo su:
- Asks for your password (the user running sudo)
- Sudo logs the command to syslog
- Requires sudo to be configured (usually is)
- Better for audit trails
sudo -s:
- Asks for your password
- Runs the shell as root
- Similar to
sudo subut slightly different execution model
On most modern systems with sudo configured, sudo -s or sudo su is preferred. It’s auditable. If someone’s doing weird root stuff, the logs show who. If you use su root directly, the system just logs “root did something”—not helpful.
But for service account switches (no escalation to root), plain su is fine.
The Full Example
Here’s what I typically use:
# Switch to a service account, with bash, in their home dir, full envsu -s /bin/bash - appuser
# Or, if they're already running bash elsewhere and you just need their permssu -s /bin/bash appuserIf the account genuinely has no login shell and you’re in a pinch:
# They're stuck at /nologin, override itsu -s /bin/bash - nologin_user
# Test somethingwhoamipwdls -la ~/.ssh
# Exit back to your userexitThe TL;DR
- Use
su usernameto switch users, keeping your environment - Use
su - usernamefor a full login environment - Use
su -s /bin/bash usernameto override the shell in/etc/passwd - Combine them:
su -s /bin/bash - usernamefor a clean login with bash, even if they have/nologin
No more editing passwd, no more nervous “did I set it back?” moments. Just override and move on.