I have a bash backup script run as root (cron) that delegates certain tasks to other specific bash scripts owned by different users. (simplified example, principle is, some things have to be done as root, different tasks are delegated to users with the appropriate environment (oracle, amazon, …)
mkdir -p /tmp/backup$NAME
su - oracle -c "~/.backups/export-test.sh"
tar cf /tmp/backup/$NOW.tar /tmp/backup$NAME
su - amazon upload_to_amazon.sh /tmp/backup/$NOW.tar
This script itself does then some tasks as user oracle:
mkdir -p $TMP_LOCATION
cd ~/.backups
exp $TMP_LOCATION/$NAME-$NOW
When I try to mimic this behaviour in python I came up with the following (started from cron as root)
name = "oracle"
# part run as root
os.makedirs(tmp_backup + name)
os.setegid(pwd.getpwnam(name)[3])
os.seteuid(pwd.getpwnam(name)[2])
# part run as oracle
os.makedirs(tmp_location)
os.chdir(os.path.expanduser("~{user}/.backups".format(user=name)))
subprocess.check_call(["exp",
"os.path.join(tmp_location, name+'-'+now)"
])
In bash when using su -, a real new shell is invoked and all environment variables of that user are set.
How can I improve this for my python script? Is there a standard recipe I can follow? I’m thinking of environment variables, umask, …
the environment is Solaris if that might matter.
Usually because a shell runs a
.profilefile when it starts up.You have several choices.
Create a proper subprocess with
subprocess.Popento execute the shell.profile— same assu -.Carefully locate the environment variable settings and mimic them in Python. The issue is that a
.profilecan do all kinds of crazy things, making it a potential problem to determine the exact effects of the.profile.Or you can extract the relevant environment variables to make the accessible to both the shell environment and your Python programs.
First. Read the
.profilefor each user to be clear on what environment variables it sets (different from things like aliases or other craziness that doesn’t apply to your Python script). Some of these environment variables are relevant to the scripts you’re running. Some aren’t relevant.Second. Split the “relevant” environment variables into a tidy
env_backups.shscript orenv_uploads.shscript.Once you have those environment variable scripts, update your
.profilefiles to replace the environment variables settings withsource env_backup.shorsource env_uploads.sh.Third. Source the relevant
env_thisandenv_thatscripts before running the Python program. Now your Python environment shares the variables with your shell environment and you only maintain them in one place.my_script.sh
That seems best to me. (Since that’s how we do it.)