【问题标题】:Best way to add an environment variable in fabric?在结构中添加环境变量的最佳方法?
【发布时间】:2011-11-29 15:20:04
【问题描述】:

我想将一些值从结构传递到远程环境,但我没有看到一个很好的方法。到目前为止,我想出的最好的是:

with prefix('export FOO=BAR'):
    run('env | grep BAR')

这似乎确实有效,但它似乎有点 hack。

我查看了 GIT 存储库,看起来这是issue #263

【问题讨论】:

  • 但是fabric关闭连接后变量会持续存在吗?从文档(prefixshell_env)中,我了解到环境变量只会为包装的命令设置。

标签: python fabric


【解决方案1】:

从 Fabric 1.5(已发布)开始,fabric.context_managers.shell_env 可以满足您的需求。

    with shell_env(FOO1='BAR1', FOO2='BAR2', FOO3='BAR3'):
        local("echo FOO1 is $FOO1")

【讨论】:

  • 似乎不适用于 Windows。已添加支持,但不在最新版本 (1.6) 中。
  • 但是fabric关闭连接后变量会持续存在吗?从文档中我了解到,环境变量只会为包装的命令设置。
  • @glarrain 是的,这就是他们将其实现为上下文管理器的重点
  • @Anentropic 那么当上下文管理器退出时变量会被清除,这不是完全相反吗?
  • 为什么将 LocalCommand export APP_ENV="staging" 放入 ~/.ssh/config 不起作用?
【解决方案2】:

我认为您基于prefix 的解决方案是完全有效的。但是,如果您想拥有一个 shell_env 上下文管理器,就像 issue#263 中建议的那样,您可以在您的 fab 文件中使用以下替代实现:

from fabric.api import run, env, prefix
from contextlib import contextmanager

@contextmanager
def shell_env(**env_vars):
    orig_shell = env['shell']
    env_vars_str = ' '.join('{0}={1}'.format(key, value)
                           for key, value in env_vars.items())
    env['shell']='{0} {1}'.format(env_vars_str, orig_shell)
    yield
    env['shell']= orig_shell

def my_task():
    with prefix('echo FOO1=$FOO1, FOO2=$FOO2, FOO3=$FOO3'):
        with shell_env(FOO1='BAR1', FOO2='BAR2', FOO3='BAR3'):
            run('env | grep BAR')

请注意,此上下文管理器会修改 env['shell'] 而不是 env['command_prefixes'](就像 prefix 上下文管理器所做的那样),因此您:

  • 仍然可以使用prefix(参见下面的示例输出),而不会出现issue#263 中提到的交互问题。
  • 必须在使用shell_env 之前对env['shell'] 应用任何更改。否则,shell_env 的更改将被覆盖,并且环境变量将无法用于您的命令。

执行上面的fab文件时,会得到如下输出:

$ fab -H localhost my_task
[localhost] Executing task 'my_task'
[localhost] run: env | grep BAR
[localhost] out: FOO1=BAR1, FOO2=BAR2, FOO3=BAR3
[localhost] out: FOO1=BAR1
[localhost] out: FOO2=BAR2
[localhost] out: FOO3=BAR3
[localhost] out: 

Done.
Disconnecting from localhost... done.

【讨论】:

  • 我一直在使用这种技术,但我注意到在更高版本的面料中它不再有效。相反,您应该/必须使用 fabric.context_managers.shell_env 实现,它确实有效。
【解决方案3】:

Fabric 1.5.0(目前在 Git 中)将 shell 作为 local() 命名参数。 如果你在那里传递“/bin/bash”,它会将它传递给 Popen 的可执行参数。

它不会执行您的 .bashrc,因为 .bashrc 源自 bash 的交互式调用。你可以在本地获取任何你想要的文件:

local('. /usr/local/bin/virtualenvwrapper.sh && workon focus_tests && bunch local output', shell='/bin/bash')

【讨论】:

    【解决方案4】:

    另一种方法是通过命令行使用 --set 传递一个值:

    --set=domain=stackoverflow.com 
    

    然后,您可以使用 env.domain 在脚本中对其进行寻址

    http://docs.fabfile.org/en/1.11/usage/fab.html#cmdoption--set

    【讨论】:

      【解决方案5】:

      尝试使用装饰器

      from fabric.context_managers import shell_env
      from functools import wraps
      
      
      def set_env():
          def decorator(func):
              @wraps(func)
              def inner(*args, **kwargs):
                  with shell_env(DJANGO_CONFIGURATION=env.config):
                      run("echo $DJANGO_CONFIGURATION")
                      return func(*args, **kwargs)
              return inner
          return decorator
      
      
      @task
      @set_env()
      def testme():
          pass
      

      【讨论】:

        猜你喜欢
        • 2018-11-09
        • 1970-01-01
        • 2021-11-04
        • 1970-01-01
        • 2015-03-23
        • 2014-02-15
        • 1970-01-01
        • 2014-10-04
        • 2019-09-08
        相关资源
        最近更新 更多