How to Bypass User Shell in su Command When Target Shell Is Missing


29 views

When executing commands via su as another user, the system attempts to spawn the target user's configured shell (from /etc/passwd) before running the command. This becomes problematic when:


su - -c 'mkdir bin' user1
# Fails with: su: /usr/bin/ksh: No such file or directory

Option 1: Force bash/sh Execution

Override the shell temporarily using env:


su - user1 -s /bin/sh -c 'mkdir bin'
# Or for more complex commands:
su - user1 -s /bin/bash -c 'export PATH=/usr/local/bin:$PATH; mkdir bin'

Option 2: Direct Command Execution

Use sudo (if available) to bypass shell entirely:


sudo -u user1 mkdir bin

Option 3: Permanent Fix

Change the user's shell configuration:


# As root:
chsh -s /bin/bash user1
# Or edit /etc/passwd directly

The su command behavior stems from Linux PAM (Pluggable Authentication Modules) configuration. You can examine the exact flow using:


strace -f su - user1 -c "echo test" 2>&1 | grep execve

This reveals the exact shell execution attempt before command processing.

For automation scripts, consider these robust approaches:


# Using sudo with full path
sudo -u user1 /bin/bash -c 'mkdir -p /home/user1/bin'

# Or with environment preservation
sudo -u user1 -i -- env PATH=$PATH /bin/sh -c 'complex_command'

Remember that some systems may have SELinux or AppArmor policies that affect shell switching behavior.

For system administrators managing multiple users:


# Batch change shells for users with missing shells
getent passwd | grep '/usr/bin/ksh' | cut -d: -f1 | while read user; do
  chsh -s /bin/bash "$user"
done

When executing commands with su while specifying another user, the system attempts to use the target user's default shell (as defined in /etc/passwd). This becomes problematic when:

  • The specified shell isn't installed (ksh in your case)
  • The shell exists but isn't functional
  • You need to bypass shell-specific initialization files

The most straightforward method is using the --shell parameter (GNU coreutils implementation):

su - --shell=/bin/bash -c 'mkdir bin' user1

This forces the system to use /bin/bash regardless of the user's default shell setting.

If you have sudo privileges, this completely bypasses the shell issue:

sudo -u user1 mkdir bin

Benefits include:

  • No shell switching occurs
  • Cleaner process inheritance
  • Better audit logging

For systems without GNU coreutils:

su - user1 -c 'exec /bin/bash -c "mkdir bin"'

For recurring issues, consider modifying /etc/default/su (Debian) or equivalent:

# Force fallback shell
ALWAYS_SET_PATH=yes
SHELL=/bin/bash

When debugging shell issues:

# Verify user's shell setting
getent passwd user1 | cut -d: -f7

# Test shell availability
which ksh bash sh

Be aware that shell forcing may:

  • Bypass security profiles (like rbash restrictions)
  • Skip important environment initialization
  • Affect expected PATH resolution