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"}
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
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). Adicionarreplace_env=False
corrigiu.Edit: vejo de acordo com os docs :
Foi um pouco confuso para mim, já que estava tentando executar um comando local.