0

我有一台服务器来安装包含postinst脚本的不同 debian 软件包。

一些软件包需要一个修改过的环境,其中包含一些要连接的端口。

当我调用服务器安装包时,我在请求中传递了一个vars包含自定义端口的对象参数: {'vars': {'CUSTOM_PORT_1': '7755', 'CUSTOM_PORT_2': '7766'}}

在我的代码中,我调用subprocess.Popen运行将安装 debian 包的命令。这是我的代码:

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

我希望修改后的环境将通过传递给postinst脚本,env=my_env这样我就可以将它们打印出来。该postinst脚本运行一个应用程序,该应用程序使用修改后的环境中的这些端口,因此我必须在运行应用程序之前将它们导出。这是postinst脚本中的代码:

#!/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*

不幸的是,这是输出:

CUSTOM_PORT_1: 
CUSTOM_PORT_2:

APP_PORT_1: 
APP_PORT_2:

我必须提到我还subprocess.Popen以其他几种方式尝试了这条线:

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)

有什么我想念的吗?

我的期望合理吗?

这甚至可能吗?

4

1 回答 1

0

好吧,我刚刚了解到,使用sudo本地用户环境变量运行命令时与 root 用户不同。

为了在使用 运行命令时保留环境变量,您应该按照此答案how-to-keep-environment-variables-when-using-sudo中的描述sudo添加标志。-E

我从how-to-keep-environment-variables-when-using-sudo复制了手册页中的引用:

-E, --preserve-env
向安全策略指示用户希望保留其现有环境变量。如果用户没有保护环境的权限,安全策略可能会返回错误。

一旦我将命令字符串更改为sudo -E dpkg -i path-to-packagepostinst脚本就能够按我的预期打印出变量:

CUSTOM_PORT_1: 7755
CUSTOM_PORT_2: 7766

APP_PORT_1: 7755
APP_PORT_2: 7766
于 2021-12-30T15:55:17.573 回答