Python 环境=。。。不设置远程环境

Python 环境=。。。不设置远程环境,python,ssh,airflow,Python,Ssh,Airflow,我正在修改调用进程的环境,并将其附加到路径,同时设置一些新的环境变量。但是,当我在子进程中打印os.environ时,这些更改不会反映出来。知道会发生什么吗 我对实例上的脚本的调用: ssh_hook = SSHHook(conn_id=ssh_conn_id) temp_env = os.environ.copy() temp_env["PATH"] = "/somepath:"+temp_env["PATH"] run = SSHExecuteOperator( bash_c

我正在修改调用进程的环境,并将其附加到路径,同时设置一些新的环境变量。但是,当我在子进程中打印os.environ时,这些更改不会反映出来。知道会发生什么吗

我对实例上的脚本的调用:

ssh_hook = SSHHook(conn_id=ssh_conn_id)
temp_env = os.environ.copy()
temp_env["PATH"] = "/somepath:"+temp_env["PATH"]
run = SSHExecuteOperator(
        bash_command="python main.py",
        env=temp_env,
        ssh_hook=ssh_hook,
        task_id="run",
        dag=dag)
说明:实施分析 如果查看气流的源,您将看到它根本没有将
env
参数合并到远程运行的命令中。将
env=
传递到钩子上的
Popen()
调用,但只将其传递到本地
子流程.Popen()
实现,而不是传递到远程操作

因此,简而言之:Airflow不支持通过SSH传递环境变量。如果要获得这种支持,它需要将它们合并到远程执行的命令中,或者为每个要发送的命令在本地执行的ssh命令中添加
SendEnv
选项(只有在远程sshd配置了
AcceptEnv
whitelisting要接收的特定环境变量名的情况下,这一点才起作用)


解决方法:在命令行上传递环境变量
解决方法:远程寻源 如果您的环境变量是敏感的,并且您不希望使用命令记录它们,那么您可以将它们传输到带外,并为包含它们的远程文件提供源

from pipes import quote

def with_env_from_remote_file(filename, command):
  return "set -a; . %s; %s" % (quote(filename), command)

SSHExecuteOperator(bash_command=with_env_from_remote_file(envfile, "python main.py"),
                   ssh_hook=ssh_hook, task_id="run", dag=dag)

请注意,
set-a
指示shell导出所有定义的变量,因此正在执行的文件只需要使用
key=val
声明定义变量;它们将自动导出。如果从Python脚本生成此文件,请确保使用
pipes.quote()引用键和值
以确保它只执行赋值而不运行其他命令。
关键字是与bash
源代码
命令等效的POSIX兼容的关键字。

请提供一个。特别是如果您使用了
ssh
(通过标记而不是标题或文本暗示),手头有很多变量。我只是通过ssh连接到一个计算引擎实例,并在那里运行一个脚本。我使用SSHExecuteOperator通过airflow使用一个服务帐户来执行此操作。提供代码意味着公开凭据。部分原因是,人们尝试测试自己的答案时,可以在自己的操作系统上运行WN机器(否则它不是可验证的)-所以你不想包括环境特定的凭据(或环境特定的代码)不管怎样,BTW,作为一个依赖于较少的魔法在气流中,考虑<代码> BasHyCuth= =“EnvFo= bar Python Maul.Py”运行
python main.py
,并在环境中导出
foo
,值为
bar
。如果即使完成了更改,也没有反映出更改,这就提供了令人信服的证据,表明您的更改在流程启动后正在被替换/覆盖/备份。这是有意义的。我想防止将其放入命令中但是,由于命令已被记录,密钥需要保持安全。另一件有趣的事情是,在gce上,在我的脚本中运行os.system(“cat xyx.txt”)时,它可以正常工作,但必须打开(“xyz.txt”)作为blah…会导致一个IOError。环境到底发生了什么?但是如果你看一下SSHHook的Popen方法,它会将env etc作为**kwargs并将其传递给另一个对Popen的调用,例如:prefixed_cmd=self。_prepare_命令(cmd)return subprocess.Popen(prefixed_cmd,**kwargs)是的,但这被传递到本地执行
ssh
命令。没有任何操作会告诉
ssh
将其发送到远程系统——您需要将
SendEnv
AcceptEnv
组合在一起,如本答案中所述,才能产生这种效果。您可以在不涉及Python的情况下自行测试:
foo=“bar”ssh localhost'echo“$foo”
将看不到
bar
的值。这完全是OpenSSH.riiilight的标准语义。因此,我尝试在服务器上的文件中设置密钥,并使用os.system来生成该文件。它仍然没有设置我需要的环境变量。
os.system()
启动一个新的shell,该shell会在调用返回时立即退出。问题应该很明显:变量可能会临时设置在该新shell中,但一旦您的
system()
调用返回,该shell将不再运行。
from pipes import quote

def with_env_from_remote_file(filename, command):
  return "set -a; . %s; %s" % (quote(filename), command)

SSHExecuteOperator(bash_command=with_env_from_remote_file(envfile, "python main.py"),
                   ssh_hook=ssh_hook, task_id="run", dag=dag)