Най-добрият начин за добавяне на променлива на средата в плат?

Бих искал да предам няколко стойности от fabric в отдалечената среда и не виждам чудесен начин да го направя. Най-доброто, което съм измислил досега, е:

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

Това изглежда работи, но изглежда като хак.

Погледнах в хранилището на GIT и изглежда, че това е проблем #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, можете да използвате следната алтернативна реализация във вашите 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 (вижте примерен резултат по-долу) без проблемите с взаимодействието, споменати в проблем №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) приема shell като 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