使用env = ...的气流SSHExecuteOperator()不设置远程环境

时间:2017-05-24 18:16:29

标签: python ssh airflow

我正在修改调用进程的环境并附加到它的PATH以及设置一些新的环境变量。但是,当我在子进程中打印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)

1 个答案:

答案 0 :(得分:3)

说明:实施分析

如果您查看Airflow SSHHook class的来源,您会发现它没有将env参数合并到远程运行所有的命令中。 SSHExecuteOperator implementationenv=传递给Popen()电话号码,但只会将其传递给本地subprocess.Popen()实施,远程操作。

因此,简而言之:Airflow不支持通过SSH传递环境变量。如果要获得这样的支持,则需要将它们合并到远程执行的命令中,或者将SendEnv选项添加到本地执行的ssh命令中以便发送每个命令(即使这样也是如此)仅当远程sshd配置为AcceptEnv将要接收的特定环境变量名称列入白名单时才有效。

解决方法:在命令行上传递环境变量

from pipes import quote # in Python 3, make this "from shlex import quote"

def with_prefix_from_env(env_dict, command=None):
    result = 'set -a; '
    for (k,v) in env_dict.items():
        result += '%s=%s; ' % (quote(k), quote(v))
    if command:
        result += command
    return result

SSHExecuteOperator(bash_command=prefix_from_env(temp_env, "python main.py"),
                   ssh_hook=ssh_hook, task_id="run", dag=dag)

解决方法:远程采购

如果您的环境变量是敏感的,并且您不希望使用该命令记录它们,则可以在带外传输它们并获取包含它们的远程文件。

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 source命令兼容的POSIX。