pythonenvironment-variablessubprocessdpkgpost-install

Python subprocess.Popen pass modified environment to use new environment varibels in postinst script


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?


Solution

  • 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