在fabric中添加环境变量的最佳方法?

43 投票
5 回答
29689 浏览
提问于 2025-04-17 07:19

我想把一些值从fabric传到远程环境,但我找不到一个好的方法。到目前为止,我想到的最好办法是:

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

这个方法似乎可以用,但感觉有点像是变通的办法。

我查看了GIT仓库,发现这似乎是第263个问题

5 个回答

2

Fabric 1.5.0(目前在Git上)把shell作为local()的一个参数。如果你在这里传入'/bin/bash',它会把这个路径传给Popen的可执行文件参数。

不过,它不会执行你的.bashrc文件,因为.bashrc文件是在交互式调用bash时加载的。你可以在local中加载你想要的任何文件:

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

我觉得你基于prefix的解决方案是完全可以的。不过,如果你想要一个像在issue#263中提到的那样的shell_env上下文管理器,你可以在你的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'],而不是像prefix上下文管理器那样修改env['command_prefixes'],所以你:

  • 仍然可以使用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.
61

从fabric 1.5版本开始(已经发布),fabric.context_managers.shell_env可以满足你的需求。

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

撰写回答