Fabric: ファブリックは、Invokeのように環境をローカルシェルに渡しません

作成日 2018年05月11日  ·  14コメント  ·  ソース: fabric/fabric

fabfile.pytasks.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)

PATH変数をチェックして機能するために必要な実行可能ファイルが存在することをチェックするfpmを使用しようとしたときに、最初にこれを見つけました。

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:FalseではなくTrue。これにより、リモートコマンドは、現在のプロセス環境のコピーを継承する代わりに、「クリーンな」空の環境で実行されます。

ローカルコマンドを実行しようとしていたので、少し混乱しました。

全てのコメント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言語を使用している場合)、 TMPDIRHOMESSH_AUTH_SOCK 、..。

私はローカルタスクについてのみ話していることに注意してください。 ローカルコマンドの受け渡し環境がデフォルトでオンになっていることを確認するTODOコメントも発見しまし

ああ、なるほど、理にかなっている

@justinasローカルタスクに

from invoke import run as local

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

これは#1752のファセットです。目的は、 localがInvokeのように動作して環境を保持し、 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"

はい、それを知ってください、ありがとう!

今のところ、IIRC、それを回避するためにrun('...', preserve_env=True)と言うことができます。

preserve_envは存在しないようです。 たぶんあなたはreplace_env=Falseか?
それはエラーを引き起こしませんが、環境はまだ破棄されています。

PS:ローカルではなく、リモートタスクの環境を設定する必要があります。

ええ、私はreplace_envを意味しました、そしてそれがうまくいかないのは奇妙です。 ローカル/リモート間で構成を分割するようになったときに見ていきます(#1752)

私もこれに出くわしました。 私はc.run('make build')を実行していましたが、ENVがプルスルーされませんでした(具体的には、ビルドが失敗する原因となったGOPATH)。 replace_env=False追加すると修正されました。

編集:私はドキュメントによるとわかります:

run.replace_env:FalseではなくTrue。これにより、リモートコマンドは、現在のプロセス環境のコピーを継承する代わりに、「クリーンな」空の環境で実行されます。

ローカルコマンドを実行しようとしていたので、少し混乱しました。

ローカルコマンドを実行しても問題は解決しません。 @bitprophet

このページは役に立ちましたか?
0 / 5 - 0 評価