Fabric: Fabric不会像Invoke那样将环境传递给本地Shell

创建于 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)

我最初在尝试使用fpm时发现了这一点,它会检​​查PATH变量来检查其运行所需的可执行文件是否存在:

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修复它。

编辑:我根据docs看到:

run.replace_env:为True,而不是False,以便远程命令在“干净”的空环境中运行,而不是继承当前进程环境的副本。

自从我尝试运行本地命令以来,这让我有些困惑。

所有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.

可以尝试通过收集整个本地环境并将其设置在另一侧来遍历所有环境变量,但是有很多数字需要忽略,因为它们会与远程系统的适当值冲突,例如PATHGOPATH (如果您使用Go语言), TMPDIRHOMESSH_AUTH_SOCK ,...

请注意,我仅在谈论本地任务。 我什至发现了一个TODO注释,该

啊,我明白了

@justinas我最终对本地任务使用了invoke from run,我这样导入它:

from invoke import run as local

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

这是#1752的一个方面-目的是让local表现得像Invoke并保留env,并让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"

是的,知道这一点,谢谢!

您可以说run('...', preserve_env=True)现在可以解决这个问题,IIRC。

preserve_env似乎不存在。 也许您是指replace_env=False吗?
那不会触发错误,但是环境仍然被丢弃。

PS:我需要为远程任务而不是本地任务设置环境。

是的,我的意思是replace_env ,这很奇怪,没用。 我将在本地/远程之间拆分配置时看一下(#1752)

我也碰到了这个。 我当时在做c.run('make build') ,但我的ENV都没有通过(特别是导致构建失败的GOPATH)。 添加replace_env=False修复它。

编辑:我根据docs看到:

run.replace_env:为True,而不是False,以便远程命令在“干净”的空环境中运行,而不是继承当前进程环境的副本。

自从我尝试运行本地命令以来,这让我有些困惑。

运行本地命令时问题仍然存在。 @bitprophet

此页面是否有帮助?
0 / 5 - 0 等级