How to Execute Commands as a NOLOGIN User in Linux (su/sudo Workarounds)


31 views

When a user account is configured with /usr/sbin/nologin or /bin/false as their shell in /etc/passwd, standard methods like su or sudo fail because these shells prevent interactive login. However, system services and cron jobs routinely execute commands as such users - so how do they bypass this restriction?

The most straightforward solution is to force a valid shell during command execution:

su -s /bin/bash testuser -c "/path/to/script.sh"

Key parameters:

  • -s /bin/bash: Temporarily overrides the nologin shell
  • testuser: Target user account
  • -c: Command to execute

For systems with sudo configured, you can use:

sudo -u testuser /bin/bash -c "/path/to/script.sh"

This approach is particularly useful when you need to:

  • Preserve environment variables
  • Execute complex commands with pipes/redirections
  • Maintain strict permission controls

For persistent scripts, consider setting the script's permissions:

chown testuser:testgroup /path/to/script.sh
chmod 4750 /path/to/script.sh

This makes the script:

  • Owned by the nologin user
  • Executable by group members
  • Run with owner's privileges via setuid bit

Database Maintenance Scenario:

#!/bin/bash
# Script to run as postgres user (nologin shell)
su -s /bin/bash postgres -c "/usr/lib/postgresql/14/bin/pg_dumpall | gzip > /backups/db-$(date +%F).gz"

Cron Job Alternative:

# In crontab -e
0 3 * * * root /bin/bash -c 'su -s /bin/sh backupuser -c "/opt/scripts/nightly-backup.sh"'

When working around nologin restrictions:

  • Always specify full paths to binaries
  • Limit sudo privileges to specific commands
  • Avoid world-writable scripts when using setuid
  • Consider creating dedicated service accounts with minimal privileges

The techniques shown here mirror how system services like MySQL, PostgreSQL, and Nginx execute commands under their respective nologin users while maintaining security boundaries.


When working with system accounts in Linux that have their shell set to /usr/sbin/nologin or /bin/false, administrators often face difficulties executing commands as these users. This is particularly common with service accounts that shouldn't have interactive login capabilities but still need to run specific processes.

The fundamental issue arises because standard methods like su or sudo typically require the target user to have a valid shell. When you try:

su -c "/bin/touch /tmp/test" testuser

You'll encounter an error if testuser has nologin shell. While changing the shell to /bin/bash temporarily would work, it's not a secure or permanent solution for service accounts.

Here are several reliable methods to execute commands as nologin users:

Method 1: Using su with Explicit Shell Specification

su -s /bin/sh testuser -c "/path/to/your/script.sh"

This forces the use of /bin/sh just for this command execution while keeping the user's shell as nologin in /etc/passwd.

Method 2: sudo with Shell Override

sudo -u testuser /bin/sh -c "/path/to/your/script.sh"

This approach is particularly useful when you have sudo privileges configured for the operation.

Method 3: Using runuser (RHEL/CentOS)

runuser -s /bin/sh -l testuser -c "/path/to/your/script.sh"

This is specific to RedHat-based distributions and provides a clean way to run commands as another user.

Let's consider a practical example where you need to run a backup script as the backupuser which has nologin shell:

#!/bin/bash
# backup_script.sh
tar -czf /backups/$(date +%Y%m%d).tar.gz /important/data

To execute this as backupuser:

su -s /bin/bash backupuser -c "/path/to/backup_script.sh"

When implementing these solutions:

  • Always use full paths to scripts and binaries
  • Limit sudo privileges when possible
  • Consider filesystem permissions for the target user
  • Audit commands run through these methods

For complex scenarios, create a wrapper script:

#!/bin/bash
# run_as_nologin.sh
USER=$1
shift
COMMAND="$@"

if grep "^$USER:" /etc/passwd | grep -q "nologin"; then
    su -s /bin/sh "$USER" -c "$COMMAND"
else
    echo "User $USER has valid shell, using standard su"
    su - "$USER" -c "$COMMAND"
fi

Usage:

./run_as_nologin.sh testuser /path/to/script.sh arg1 arg2