Лучший способ добавить переменную среды в ткань?

Я хотел бы передать несколько значений из ткани в удаленную среду, и я не вижу хорошего способа сделать это. Лучшее, что я придумал до сих пор, это:

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

Кажется, это работает, но это похоже на взлом.

Я заглянул в репозиторий GIT, и оказалось, что это issue #263.


person David Parmenter    schedule 29.11.2011    source источник
comment
Но будут ли переменные сохраняться после того, как ткань закроет соединение? Из документации (prefix и shell_env) я понимаю, что переменные среды будут установлены только для обернутых команд.   -  person glarrain    schedule 17.07.2013


Ответы (5)



Я думаю, что ваше решение на основе prefix совершенно верно. Однако, если вы хотите иметь менеджер контекста shell_env, предложенный в issue#263, вы можете использовать следующая альтернативная реализация в ваших потрясающих файлах:

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.
  • необходимо применить любые изменения к env['shell'] перед использованием shell_env. В противном случае 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.
person jcollado    schedule 10.12.2011
comment
Я использовал эту технику, но заметил, что в более поздних версиях ткани она больше не работает. Вместо этого вы должны/должны использовать реализацию fabric.context_managers.shell_env, которая действительно работает. - person Jason R. Coombs; 14.06.2015

Fabric 1.5.0 (в настоящее время в Git) принимает оболочку в качестве именованного аргумента local(). Если вы передаете туда '/bin/bash', он передает его исполняемому аргументу Popen.

Однако он не будет выполнять ваш .bashrc, потому что .bashrc создается при интерактивном вызове bash. Вы можете получить любой файл, который хотите, внутри локального:

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

Другой способ — передать значение через командную строку с --set:

--set=domain=stackoverflow.com 

Затем вы можете обратиться к нему в скрипте с помощью env.domain

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

person Vasili Pascal    schedule 25.05.2016

Попробуйте использовать декоратор

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
person Aibek Prenov    schedule 05.05.2018