Considere esta definición de tarea, guardada como fabfile.py
y tasks.py
:
from invoke import task
<strong i="8">@task</strong>
def make(c):
c.run('env')
fab make
salidas:
PWD=/tmp
SHLVL=1
_=/usr/bin/env
inv make
salidas:
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)
Inicialmente encontré esto cuando intenté usar PATH
para verificar que los ejecutables que requiere para funcionar existen:
from invoke import task
<strong i="22">@task</strong>
def make(c):
c.run('fpm -s dir -t rpm -C dist --name somename .')
Esto funciona con invoke, pero no con 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"}
Descubrí la descripción de este comportamiento. Sin embargo, no tiene sentido cuando se ejecuta el comando localmente
Esto es típico para ejecutar comandos en 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.
Se podría intentar pasar a través de todas las variables de entorno recopilando todo el entorno local y configurándolas en el otro lado, pero hay bastantes números que deberían ignorarse porque entrarían en conflicto con el valor apropiado para el sistema remoto, como PATH
, GOPATH
(si usa el idioma Go), TMPDIR
, HOME
, SSH_AUTH_SOCK
, ...
Tenga en cuenta que estoy hablando únicamente de tareas locales. Incluso descubrí un comentario TODO que confirma que el entorno de paso debe estar activado de forma predeterminada para los comandos locales.
ah, ya veo, tiene sentido
@justinas Terminé usando ejecutar desde invocar para tareas locales, lo importo así:
from invoke import run as local
<strong i="7">@task</strong>
def test(c):
local('ls')
Esta es una faceta de # 1752: la intención es que local
comporte como Invocar y conservar el env, y que run
comporte correctamente como SSH y descarte el env. Sin embargo, en este momento, las configuraciones que impulsan este comportamiento no están divididas correctamente; de hecho, es un error. Lo arreglaremos pronto.
¡Gracias por la respuesta!
Me encontré con el mismo problema y solo quería señalar que no es solo el entorno local lo que se descarta.
Quizás ya esté al tanto de este error.
Para aclarar, esto no funcionó para mí:
<strong i="8">@task</strong>
def test(c):
c.run('echo $ENV', env={'ENV': 'production'}) # no output
Por el momento, encontré esta solución (no muy limpia) que puedo usar:
<strong i="12">@task</strong>
def test(c):
with c.prefix('ENV=production'):
c.run('echo $ENV') # prints "production"
Sí, consciente de eso, ¡gracias!
Puede decir run('...', preserve_env=True)
para solucionar eso por ahora, IIRC.
preserve_env
no parece existir. ¿Quizás te estabas refiriendo a replace_env=False
?
Eso no desencadena un error, pero el entorno aún se descarta.
PD: necesito configurar el entorno para tareas remotas, no locales.
Sí, me refiero a replace_env
y es extraño que eso no funcione. Echaré un vistazo cuando pueda dividir la configuración entre local / remoto (# 1752)
También me encontré con esto. Estaba haciendo c.run('make build')
y ninguno de mi ENV se superó (específicamente GOPATH, que causó que la compilación fallara). Agregar el replace_env=False
solucionó.
Editar: veo de acuerdo con los documentos :
run.replace_env: Verdadero, en lugar de Falso, para que los comandos remotos se ejecuten con un entorno 'limpio' y vacío en lugar de heredar una copia del entorno del proceso actual.
Fue un poco confuso para mí ya que estaba tratando de ejecutar un comando local.
El problema sigue ahí cuando se ejecuta el comando local. @bitprophet
Comentario más útil
También me encontré con esto. Estaba haciendo
c.run('make build')
y ninguno de mi ENV se superó (específicamente GOPATH, que causó que la compilación fallara). Agregar elreplace_env=False
solucionó.Editar: veo de acuerdo con los documentos :
Fue un poco confuso para mí ya que estaba tratando de ejecutar un comando local.