I have a server to install different debian packages that contain a postinst
script.
Some packages require a modified environment containing some ports to connect to.
When I call the server to install the package, I pass in the request an object parameter vars
containing the custom ports:
{'vars': {'CUSTOM_PORT_1': '7755', 'CUSTOM_PORT_2': '7766'}}
In my code I call subprocess.Popen
to run a command that will install the debian package. Here's my code:
def open_process(command, app_vars=None):
my_env = os.environ.copy()
if app_vars:
my_env.update(app_vars)
p = subprocess.Popen(['sudo', 'dpkg', '-i', 'path-to-package'], env=my_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
output, err = p.communicate()
return_code = p.returncode
return output, err, return_code
I expected that the modified environment will be passed to the postinst
script, via env=my_env
so I can print them out. The postinst
script runs an app that uses these ports from the modified environment, so I must export them before I run the app. Here is the code from the postinst
script:
#!/bin/bash
.
.
.
echo "CUSTOM_PORT_1:$CUSTOM_PORT_1"
echo "CUSTOM_PORT_2:$CUSTOM_PORT_2"
export APP_PORT_1=$CUSTOM_PORT_1
export APP_PORT_2=$CUSTOM_PORT_2
echo "APP_PORT_1:$APP_PORT_1"
echo "APP_PORT_2:$APP_PORT_2"
.
.
.
*run-the-app*
Unfortunately, this is the output:
CUSTOM_PORT_1:
CUSTOM_PORT_2:
APP_PORT_1:
APP_PORT_2:
I must mention I also tried the subprocess.Popen
line in a few additional ways:
1.
p = subprocess.Popen(['sudo dpkg -i /path-to-package', env=my_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
def open_process(command, app_vars=None):
if app_vars:
for key in app_vars:
os.environ[key] = app_vars.get(key)
p = subprocess.Popen(['sudo', 'dpkg', '-i', 'path-to-package'], env={**os.environ}, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
Is there anything I'm missing?
Are my expectations reasonable?
Is this even possible?
Well I just learned that when running a command with sudo
the local user environment variables are not the same as the root user.
In order to preserve the environment variables when running a command with sudo
, you should add the flag -E
as described in this answer how-to-keep-environment-variables-when-using-sudo.
I copied from how-to-keep-environment-variables-when-using-sudo the quote from the man page:
-E, --preserve-env
Indicates to the security policy that the user wishes to preserve their existing environment variables. The security policy may return an error if the user does not have permission to preserve the environment.
Once I changed the command string to sudo -E dpkg -i path-to-package
, the postinst
script was able to print out the variables as I expected:
CUSTOM_PORT_1: 7755
CUSTOM_PORT_2: 7766
APP_PORT_1: 7755
APP_PORT_2: 7766