How to Temporarily Switch to www-data User in BASH Script for Single Command Execution


2 views

When automating server tasks like Subversion repository creation, we often need to execute specific commands as different users. A common scenario is creating SVN repositories where the svnadmin create command must run as the web server user (typically www-data) while the rest of the script executes as root.

Proper permission handling is crucial for security and functionality. The www-data user needs ownership of repository files for the web server to access them, but the setup script often requires root privileges for other operations.

The most straightforward approach is using sudo -u to execute a single command as another user:

#!/bin/bash
# Verify root privileges
if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root" 1>&2
    exit 1
fi

# Create repository as www-data
sudo -u www-data svnadmin create /svn/repository

# Continue with root operations
chown -R www-data:www-data /svn/repository
svn mkdir file:///svn/repository/trunk -m "Initial structure"

For systems where sudo isn't available or preferred, you can use su with the -c flag:

su www-data -c "svnadmin create /svn/repository"

When switching users, environment variables might not carry over. Use env to preserve specific variables:

sudo -u www-data env PATH=$PATH svnadmin create /svn/repository

Here's a more complete script demonstrating the pattern:

#!/bin/bash
# Repository creation script
REPO_PATH="/svn/newrepo"

# Validate root
[ "$(id -u)" = "0" ] || { echo "Root required"; exit 1; }

# Create as www-data
sudo -u www-data svnadmin create "$REPO_PATH"

# Post-creation setup
chmod -R 775 "$REPO_PATH"
svn mkdir "file://$REPO_PATH/trunk" -m "Initial trunk"
svn mkdir "file://$REPO_PATH/branches" -m "Initial branches"
svn mkdir "file://$REPO_PATH/tags" -m "Initial tags"

After repository creation, ensure proper permissions:

chown -R www-data:www-data /svn
find /svn -type d -exec chmod 775 {} \;
find /svn -type f -exec chmod 664 {} \;

Add basic error checking to make the script more robust:

sudo -u www-data svnadmin create "$REPO_PATH" || {
    echo "Repository creation failed"
    exit 1
}

When automating server administration tasks, we often encounter situations where a single command needs to run under a different user context while maintaining the overall script's elevated privileges. In your case with Subversion repository setup, the svnadmin create command must execute as www-data while other operations require root access.

Here are three robust approaches to handle this scenario:

Method 1: Using sudo -u

#!/bin/bash
# Verify root privileges
if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root" 1>&2
    exit 1
fi

# Execute as www-data
sudo -u www-data svnadmin create /svn/repository

# Continue with root operations
chown -R www-data:www-data /svn/repository
chmod -R 775 /svn/repository

Method 2: Using su with -c flag

#!/bin/bash
# Root check omitted for brevity

# Execute single command as www-data
su www-data -c "svnadmin create /svn/repository"

# Post-commands as root
svnadmin verify /svn/repository
systemctl restart apache2

Method 3: Heredoc Approach

For more complex operations that might need multiple commands:

#!/bin/bash
su www-data <<'EOF'
svnadmin create /svn/repository
exit
EOF

# Back to root context
ln -s /svn/repository /var/www/html/repo

When implementing these solutions:

  • Always validate paths and permissions before operations
  • Consider adding error handling with set -e or explicit checks
  • For production scripts, add logging of user context switches
  • Test permission inheritance in your specific environment

If you need to maintain environment variables during the switch:

sudo -E -u www-data svnadmin create /svn/repository

Or with su:

su - www-data -c "svnadmin create /svn/repository"