Fabric: O Fabric não passa o ambiente para um shell local como o Invoke faz

Criado em 11 mai. 2018  ·  14Comentários  ·  Fonte: fabric/fabric

Considere esta definição de tarefa, salva como fabfile.py e tasks.py :

from invoke import task

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

fab make saídas:

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

inv make saídas:

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)

Eu inicialmente encontrei isso ao tentar usar o fpm, que verifica a variável PATH para verificar se os executáveis ​​necessários para funcionar existem:

from invoke import task

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

Isso funciona com invoke, mas não com 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()

Comentários muito úteis

Eu também corri para isso. Eu estava fazendo c.run('make build') e nenhum dos meus ENV funcionou (especificamente GOPATH que causou a falha da compilação). Adicionar replace_env=False corrigiu.

Edit: vejo de acordo com os docs :

run.replace_env: True, em vez de False, para que os comandos remotos sejam executados com um ambiente 'limpo' e vazio em vez de herdar uma cópia do ambiente do processo atual.

Foi um pouco confuso para mim, já que estava tentando executar um comando local.

Todos 14 comentários

Eu descobri a descrição desse comportamento. No entanto, não faz sentido ao executar o comando localmente

Isso é típico para executar comandos em sistemas remotos:

$ 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.

Pode-se tentar passar por todas as variáveis ​​de ambiente coletando todo o ambiente local e definindo-as do outro lado, mas há um grande número que precisaria ser ignorado porque entraria em conflito com o valor apropriado para o sistema remoto, como PATH , GOPATH (se você usar a linguagem Go), TMPDIR , HOME , SSH_AUTH_SOCK , ...

Observe que estou falando apenas sobre tarefas locais. Eu até descobri um comentário TODO que confirma que o ambiente de passagem deve estar ativado por padrão para comandos locais.

ah, entendo, faz sentido

@justinas acabei usando run from invoke para tarefas locais, eu importo assim:

from invoke import run as local

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

Esta é uma faceta de # 1752 - a intenção é que local se comporte como Invoque e preserve o env, e que run se comporte corretamente como SSH e descarte o env. No entanto, no momento, as configurações que conduzem esse comportamento não estão devidamente divididas - é efetivamente um bug. Estaremos consertando isso em breve.

Obrigado pela resposta!

Acabei de me deparar com o mesmo problema e só queria observar que não é apenas o ambiente local que é descartado.

Talvez você já esteja ciente desse bug também.

Para esclarecer, isso não funcionou para mim:

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

Por enquanto, encontrei esta solução alternativa (não muito limpa) que posso usar:

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

Sim, ciente disso, obrigado!

Você pode dizer run('...', preserve_env=True) para contornar isso por enquanto, IIRC.

preserve_env não parece existir. Talvez você esteja se referindo a replace_env=False ?
Isso não aciona um erro, mas o ambiente ainda está sendo descartado.

PS: Preciso definir o ambiente para tarefas remotas, não locais.

Sim, eu quis dizer replace_env e é estranho que isso não funcione. Vou dar uma olhada quando for dividir a configuração entre local / remoto (# 1752)

Eu também corri para isso. Eu estava fazendo c.run('make build') e nenhum dos meus ENV funcionou (especificamente GOPATH que causou a falha da compilação). Adicionar replace_env=False corrigiu.

Edit: vejo de acordo com os docs :

run.replace_env: True, em vez de False, para que os comandos remotos sejam executados com um ambiente 'limpo' e vazio em vez de herdar uma cópia do ambiente do processo atual.

Foi um pouco confuso para mim, já que estava tentando executar um comando local.

O problema ainda está presente ao executar o comando local. @bitprophet

Esta página foi útil?
0 / 5 - 0 avaliações