How to Run Commands as a System User with /bin/false Shell in Linux


2 views

When creating system users in Linux (typically via adduser --system), they're often configured with /bin/false as their shell. This is a security best practice for service accounts, but it creates a problem when you need to manually test commands as that user.

The standard su command won't work because it requires an interactive shell:

su system
This account is currently not available.

Here are several approaches to solve this:

1. Temporary Shell Modification

While you mentioned this approach, here's a more efficient way:

sudo usermod -s /bin/bash system
sudo -u system bash -c "your_command"
sudo usermod -s /bin/false system

2. Using sudo Directly

The cleanest solution is to bypass the shell requirement:

sudo -u system your_command

For multiple commands:

sudo -u system bash -c "command1 && command2"

3. Environment Preservation

When you need the user's environment:

sudo -i -u system env -i your_command

For testing cron jobs, you can use:

sudo -u system bash -c "cd / && your_cron_command"

Remember that system users exist for a reason - they shouldn't have interactive shells. Always prefer sudo -u over temporary shell changes, and revert any changes immediately after testing.

On systems with systemd:

runuser -u system -- your_command



When creating system users in Linux using adduser --system, they're typically configured with /bin/false as their shell for security reasons. This prevents interactive login while still allowing cron jobs and service operations. However, during development and debugging, we often need to test commands manually as these users.

Many admins temporarily change the shell to /bin/bash, test commands, then revert back:

# Not recommended for production
sudo usermod -s /bin/bash system_user
sudo -u system_user bash -c "your_command"
sudo usermod -s /bin/false system_user

This approach creates security gaps and is inefficient for frequent testing.

Method 1: Using sudo with explicit command

sudo -u system_user COMMAND="your_command" sh -c '$COMMAND'

Method 2: Temporary shell with command execution

sudo -u system_user /bin/sh -c "your_command && your_other_command"

Method 3: For complex command sequences

sudo -u system_user /bin/sh <<'END_SHELL'
  command1
  command2 | grep pattern
  for i in $(seq 1 5); do
    echo "Iteration $i"
  done
END_SHELL
  • Always audit commands executed as system users
  • Monitor for privilege escalation attempts
  • Consider using --preserve-env with sudo when environment variables are needed
  • For production systems, prefer proper logging over interactive testing

For automated testing scenarios, you can incorporate these techniques into your pipelines:

- name: Test as system user
  run: |
    docker exec container sudo -u app_user /bin/sh -c "test_command"

Remember that while these methods solve the immediate problem, the best practice is to design your systems so that interactive access to system users is rarely needed.