Considérez cette définition de tâche, enregistrée à la fois sous les noms fabfile.py
et tasks.py
:
from invoke import task
<strong i="8">@task</strong>
def make(c):
c.run('env')
fab make
sorties:
PWD=/tmp
SHLVL=1
_=/usr/bin/env
inv make
sorties:
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)
J'ai initialement trouvé cela en essayant d'utiliser fpm qui vérifie la variable PATH
pour vérifier que les exécutables dont elle a besoin pour fonctionner existent:
from invoke import task
<strong i="22">@task</strong>
def make(c):
c.run('fpm -s dir -t rpm -C dist --name somename .')
Cela fonctionne avec invoke, mais pas avec 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"}
J'ai découvert la description de ce comportement. Cependant, cela n'a aucun sens lors de l'exécution de la commande localement
Ceci est typique pour l'exécution de commandes sur des systèmes distants:
$ 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.
On pourrait essayer de passer par toutes les variables d'environnement en collectant tout l'environnement local et en les définissant de l'autre côté, mais il y en a un certain nombre qui devraient être ignorés car ils seraient en conflit avec la valeur appropriée pour le système distant, comme PATH
, GOPATH
(si vous utilisez le langage Go), TMPDIR
, HOME
, SSH_AUTH_SOCK
, ...
Notez que je parle uniquement de tâches locales. J'ai même découvert un commentaire TODO qui confirme que l'environnement de passage doit être activé par défaut pour les commandes locales.
ah, je vois, ça a du sens
@justinas J'ai fini par utiliser run from invoke pour les tâches locales, je l'importe comme ceci:
from invoke import run as local
<strong i="7">@task</strong>
def test(c):
local('ls')
C'est une facette de # 1752 - l'intention est que local
se comporte comme Invoke et préserve l'environnement, et que run
se comporte correctement comme SSH et supprime l'env. Cependant, pour le moment, les configurations à l'origine de ce comportement ne sont pas correctement réparties - c'est effectivement un bogue. Nous allons le réparer bientôt.
Merci pour la réponse!
Je suis juste tombé sur le même problème et je voulais juste noter que ce n'est pas seulement l'environnement local qui est rejeté.
Peut-être que vous êtes déjà au courant de ce bogue également.
Pour clarifier, cela n'a pas fonctionné pour moi:
<strong i="8">@task</strong>
def test(c):
c.run('echo $ENV', env={'ENV': 'production'}) # no output
Pour le moment, j'ai trouvé cette solution de contournement (pas très propre) que je peux utiliser:
<strong i="12">@task</strong>
def test(c):
with c.prefix('ENV=production'):
c.run('echo $ENV') # prints "production"
Oui, conscient de cela, merci!
Vous pouvez dire run('...', preserve_env=True)
pour contourner ce problème pour le moment, IIRC.
preserve_env
ne semble pas exister. Peut-être parliez-vous de replace_env=False
?
Cela ne déclenche pas d'erreur, mais l'environnement est toujours rejeté.
PS: J'ai besoin de définir l'environnement pour les tâches distantes, pas locales.
Oui, je voulais dire replace_env
et c'est bizarre que cela ne fonctionne pas. Je jetterai un coup d'oeil quand j'arriverai à diviser la configuration entre local / distant (# 1752)
Je viens de rencontrer cela aussi. Je faisais c.run('make build')
et aucun de mes ENV n'a réussi (en particulier GOPATH qui a provoqué l'échec de la construction). L'ajout du replace_env=False
corrigé.
Edit: je vois selon la documentation :
run.replace_env: True, au lieu de False, de sorte que les commandes à distance s'exécutent avec un environnement «propre» et vide au lieu d'hériter d'une copie de l'environnement du processus actuel.
C'était juste un peu déroutant pour moi car j'essayais d'exécuter une commande locale.
Le problème est toujours là lors de l'exécution de la commande locale. @bitprophet
Commentaire le plus utile
Je viens de rencontrer cela aussi. Je faisais
c.run('make build')
et aucun de mes ENV n'a réussi (en particulier GOPATH qui a provoqué l'échec de la construction). L'ajout dureplace_env=False
corrigé.Edit: je vois selon la documentation :
C'était juste un peu déroutant pour moi car j'essayais d'exécuter une commande locale.