Using shell=True
With Your Existing Script
First, in terms of the very simplest thing -- if you're using shell=True
, you can tell the shell that starts to run the contents of your preexisting script unmodified.
That is to say -- if you were initially doing this:
subprocess.Popen(['your-command', 'arg1', 'arg2'])
...then you can do the following to execute that same command, with almost the same security guarantees (the only additional vulnerabilities, so long as the contents of file1.sh
are trusted, are to out-of-band issues such as shellshock):
# this has the security of passing explicit out-of-band args
# but sources your script before the out-of-process command
subprocess.Popen(['. "$1"; shift; exec "$@"', "_", "./file1.sh",
"your-command", "arg1", "arg2"], shell=True)
Using /proc/self/environ
to export environment variables in a NUL-delimited stream
The ideal thing to do is to export your environment variables in an unambiguous form -- a NUL-delimited stream is ideal -- and then parse that stream (which is in a very unambiguous format) in Python.
Assuming Linux, you can export the complete set of environment variables as follows:
# copy all our environment variables, in a NUL-delimited stream, to myvars.environ
cat </proc/self/environ >myvars.environ
...or you can export a specific set of variables by hand:
for varname in HORCMINST PATH; do
printf '%s=%s' "$varname" "${!varname}"
done >myvars.environ
Reading and parsing a NUL-delimited stream in Python
Then you just need to read and parse them:
#!/usr/bin/env python
env = {}
for var_def in open('myvars.environ', 'r').read().split(''):
(key, value) = var_def.split('=', 1)
env[key] = value
import subprocess
subprocess.Popen(['your-command', 'arg1', 'arg2'], env=env)
You could also immediately apply those variables by running os.environ[key]=value
.
Reading and parsing a NUL-delimited stream in bash
Incidentally, that same format is also easy to parse in bash:
while IFS= read -r -d '' var_def; do
key=${var_def%%=*}
value=${var_def#*=}
printf -v "$key" '%s' "$value"
export "$key"
done <myvars.environ
# ...put the rest of your bash script here
Now, why a NUL-delimited stream? Because environment variables are C strings -- unlike Python strings, they can't contain NUL. As such, NUL is the one and only character that can be safely used to delimit them.
For instance, someone who tried to use newlines could be stymied by an environment variable that contained a literal newline -- and if someone is, say, embedding a short Python script inside an environment variable, that's a very plausible event!