Fabric: Fabric не передает среду в локальную оболочку, как это делает Invoke.

Созданный на 11 мая 2018  ·  14Комментарии  ·  Источник: fabric/fabric

Рассмотрим это определение задачи, сохраненное как fabfile.py и tasks.py :

from invoke import task

<strong i="8">@task</strong>
def make(c):
    c.run('env')

fab make выходы:

PWD=/tmp
SHLVL=1
_=/usr/bin/env

inv make выходы:

LC_ALL=en_US.UTF-8
NVM_DIR=/home/justinas/.nvm
LC_MEASUREMENT=en_US.UTF-8
LC_PAPER=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
<...> (lots of stuff in my environment)

Первоначально я обнаружил это при попытке использовать fpm, который проверяет переменную PATH чтобы проверить, существуют ли исполняемые файлы, необходимые для работы:

from invoke import task

<strong i="22">@task</strong>
def make(c):
    c.run('fpm -s dir -t rpm -C dist --name somename .')

Это работает с invoke, но не с fab.

justinas<strong i="26">@js</strong>:/tmp$ fab make
{:timestamp=>"2018-05-11T13:11:26.218874+0300", :message=>"Need executable 'rpmbuild' to convert dir to rpm", :level=>:error}
justinas<strong i="27">@js</strong>:/tmp$ inv make
{:timestamp=>"2018-05-11T13:11:29.967762+0300", :message=>"Created package", :path=>"somename-1.0-1.x86_64.rpm"}
Bug Connection Needs investigation run()

Самый полезный комментарий

Я тоже с этим столкнулся. Я делал c.run('make build') и ни один из моих ENV не прошел (особенно GOPATH, который привел к сбою сборки). Добавление replace_env=False исправило это.

Изменить: я вижу в соответствии с документами :

run.replace_env: True вместо False, чтобы удаленные команды выполнялись с «чистой» пустой средой вместо наследования копии среды текущего процесса.

Меня это немного сбивало с толку, так как я пытался запустить локальную команду.

Все 14 Комментарий

Я обнаружил описание этого поведения. Однако в этом нет смысла запускать команду локально.

Это типично для выполнения команд в удаленных системах:

$ env | wc -l
      41
$ ssh testdeploy01.ec2.st-av.net env | wc -l
      14
$ ssh testdeploy01.ec2.st-av.net grep Env /etc/ssh/sshd_config
AcceptEnv LANG LC_*
         Specifies what environment variables sent by the client will be copied into
         the session's environ(7).  See SendEnv in ssh_config(5) for how to configure
         the client.  The TERM environment variable is always sent whenever the
         client requests a pseudo-terminal as it is required by the protocol.  Vari-
         ables are specified by name, which may contain the wildcard characters `*'
         and `?'.  Multiple environment variables may be separated by whitespace or
         spread across multiple AcceptEnv directives.  Be warned that some environ-
         ment variables could be used to bypass restricted user environments.  For
         this reason, care should be taken in the use of this directive.  The default
         is not to accept any environment variables.

Можно попытаться пройти через все переменные среды, собрав всю локальную среду и установив их на другой стороне, но есть довольно много чисел, которые нужно игнорировать, потому что они будут конфликтовать с соответствующим значением для удаленной системы, например PATH , GOPATH (если вы используете язык Go), TMPDIR , HOME , SSH_AUTH_SOCK , ...

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

ах, я вижу, имеет смысл

@justinas В итоге я использовал запуск из вызова для локальных задач, я импортирую его так:

from invoke import run as local

<strong i="7">@task</strong>
def test(c):
    local('ls')

Это аспект # 1752 - намерение состоит в том, чтобы local вел себя как Invoke и сохранял env, а run вел себя должным образом как SSH и отбрасывал env. Однако прямо сейчас конфигурации, управляющие этим поведением, не разделены должным образом - это фактически ошибка. Скоро мы это исправим.

Спасибо за ответ!

Я только что столкнулся с той же проблемой и просто хотел отметить, что отбрасывается не только локальная среда.

Возможно, вы уже знаете об этой ошибке.

Чтобы уточнить, это не сработало для меня:

<strong i="8">@task</strong>
def test(c):
    c.run('echo $ENV', env={'ENV': 'production'}) # no output

На данный момент я нашел этот обходной путь (не очень чистый), который я могу использовать:

<strong i="12">@task</strong>
def test(c):
    with c.prefix('ENV=production'):
        c.run('echo $ENV') # prints "production"

Да, в курсе, спасибо!

Вы можете сказать run('...', preserve_env=True) чтобы обойти это сейчас, IIRC.

preserve_env , похоже, не существует. Может быть, вы имели в виду replace_env=False ?
Это не вызывает ошибки, но среда по-прежнему отбрасывается.

PS: мне нужно настроить среду для удаленных задач, а не для локальных.

Да, я имел в виду replace_env и странно, что это не работает. Я посмотрю, когда мне удастся разделить конфигурацию между локальным и удаленным (# 1752)

Я тоже с этим столкнулся. Я делал c.run('make build') и ни один из моих ENV не прошел (особенно GOPATH, который привел к сбою сборки). Добавление replace_env=False исправило это.

Изменить: я вижу в соответствии с документами :

run.replace_env: True вместо False, чтобы удаленные команды выполнялись с «чистой» пустой средой вместо наследования копии среды текущего процесса.

Меня это немного сбивало с толку, так как я пытался запустить локальную команду.

Проблема все еще существует при запуске локальной команды. @bitprophet

Была ли эта страница полезной?
0 / 5 - 0 рейтинги