Skip to content
Go back

Linux su with custom shell

Updated:
By SumGuy 5 min read
Linux su with custom shell

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.

Terminal window
su username

This 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:

Terminal window
su root
su - # 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 -:

Terminal window
su username

You 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):

Terminal window
su - username
su -l username # --login, same thing

This 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:

Terminal window
su -s /bin/bash username

The -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?

  1. Service accounts with no shell. You need to debug that Jenkins user, but their shell is /nologin. One command, no editing passwd, done.
  2. Accounts with weird shells. Maybe someone left the shell set to /bin/csh or /bin/ksh, and you want bash.
  3. Consistent environment. You’re forcing bash even if the account normally uses something else.

You can combine flags:

Terminal window
su -s /bin/bash - username # login shell override
su -s /bin/sh username # just sh, keep current env

When You’d Actually Use This

Scenario 1: CI system user is broken

Terminal window
# CI user has /nologin, but you need to test a build manually
su -s /bin/bash - jenkins
# Now you're running as `jenkins`, with bash, in their home dir

Scenario 2: Debugging a cron job

Terminal window
# mediaserver user runs an encoding script, it's failing
# You need to test it as the mediaserver user
su -s /bin/bash - mediaserver
cd /opt/encoding
bash ./transcode.sh # run it exactly as the cron job does

Scenario 3: Testing file permissions

Terminal window
# A script is supposed to work as user `appuser`, but you're not sure about perms
su -s /bin/bash - appuser
ls -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 -:

sudo su:

sudo -s:

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:

Terminal window
# Switch to a service account, with bash, in their home dir, full env
su -s /bin/bash - appuser
# Or, if they're already running bash elsewhere and you just need their perms
su -s /bin/bash appuser

If the account genuinely has no login shell and you’re in a pinch:

Terminal window
# They're stuck at /nologin, override it
su -s /bin/bash - nologin_user
# Test something
whoami
pwd
ls -la ~/.ssh
# Exit back to your user
exit

The TL;DR

No more editing passwd, no more nervous “did I set it back?” moments. Just override and move on.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Linux CLI Tarball Extraction — Flags, Formats, Gotchas
Next Post
Logrotate & Compression

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts