When automating system administration tasks, you often need to execute scripts with different user privileges. The challenge is doing this securely and correctly while maintaining the target user's environment.
The simplest approach is using su
with the -c
flag to execute a single command:
su postgres -c "/path/to/backup_db.sh /tmp/test"
Key points:
- This inherits the postgres user's environment
- Works interactively (will prompt for password)
- For automation, you'll need to handle authentication
For more control, sudo
is often preferred:
sudo -u postgres /path/to/backup_db.sh /tmp/test
Advantages:
- More granular control via sudoers file
- Can be configured for passwordless execution
- Better logging of privileged operations
For system services, runuser
is often better:
runuser -u postgres -- /path/to/backup_db.sh /tmp/test
This is particularly useful in:
- Systemd service files
- Container environments
- Situations where pseudo-terminal allocation isn't needed
To preserve specific environment variables when switching users:
sudo -Hu postgres env PATH=$PATH /path/to/backup_db.sh /tmp/test
For fully automated execution:
- Configure passwordless sudo for specific commands
- Set up proper permissions on the script
- Consider using SSH key authentication if running remotely
Here's a complete example with error handling:
#!/bin/bash
SCRIPT="/opt/scripts/backup_db.sh"
ARGS="/tmp/backup"
LOG="/var/log/db_backup.log"
if sudo -u postgres "$SCRIPT" "$ARGS" >> "$LOG" 2>&1; then
echo "Backup completed successfully"
exit 0
else
echo "Backup failed - check $LOG for details" >&2
exit 1
fi
- Always use absolute paths
- Limit sudo privileges to specific commands
- Regularly audit scripts run with elevated privileges
- Consider using dedicated service accounts
When automating system tasks in Linux, we often need to execute scripts with different user privileges. The manual approach using su
works interactively but fails in automated environments because:
- It requires interactive password input
- Environment variables aren't properly inherited
- The session doesn't terminate automatically
The most robust method combines sudo
with proper configuration:
sudo -u postgres /path/to/backup_db.sh /tmp/test
Key advantages:
1. Non-interactive execution
2. Preserves target user's environment
3. Clean permission handling
First, edit the sudoers file safely with visudo
, then add:
# Allow script_user to run backup_db.sh as postgres
script_user ALL=(postgres) NOPASSWD: /path/to/backup_db.sh
For systems where sudo isn't available, use expect:
#!/usr/bin/expect -f
spawn su - postgres -c "/path/to/backup_db.sh /tmp/test"
expect "Password:"
send "postgres_password\r"
interact
When switching users, environment variables may behave differently. Test with:
sudo -u postgres env
To preserve specific variables:
sudo -u postgres -E /path/to/script.sh
Here's a complete backup script solution:
#!/bin/bash
# Configure in /etc/sudoers:
# backup_user ALL=(postgres) NOPASSWD: /usr/local/bin/pg_backup.sh
BACKUP_DIR=/var/backups/postgres
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
sudo -u postgres pg_dumpall | gzip > ${BACKUP_DIR}/pg_backup_${TIMESTAMP}.sql.gz
find ${BACKUP_DIR} -type f -mtime +30 -delete