简体   繁体   English

面料的独立fabfile?

[英]Stand-alone fabfile for fabric?

Is it possible to make the fabfile stand-alone? 是否有可能使fabfile独立?
I'm not very fond of running the external tool 'fab'. 我不太喜欢运行外部工具'fab'。 If I manage to get the fabfile standalone I can run the file from within the (Eclipse / Pydev) IDE, easily debug it, use project configurations and paths etc. 如果我设法将fabfile独立运行,我可以在(Eclipse / Pydev)IDE中运行该文件,轻松调试它,使用项目配置和路径等。
Why doesn't this work: 为什么这不起作用:

from fabric.api import run

def host_type():
    run('uname -s')

if __name__ == '__main__':
    host_type()    

I eventually found the solution (and it is really simple!). 我最终找到了解决方案(而且非常简单!)。
In my fabfile, I added: 在我的fabfile中,我补充说:

from fabric.main import main

if __name__ == '__main__':
    import sys
    sys.argv = ['fab', '-f', __file__, 'update_server']
    main()

I hope this helps people... 我希望这有助于人们......

If I recall correctly, I couldn't get the Fabric API to do what I wanted either. 如果我没记错的话,我无法让Fabric API做我想做的事情。 I decided to abandon the extra layer entirely and use Paramiko (the underlying SSH library used by Fabric) directly: 我决定完全放弃额外的层并直接使用Paramiko (Fabric使用的底层SSH库):

import os
import paramiko

ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('hostname.example.com', 22, 'username', 'password')
ssh.save_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
stdin, stdout, stderr = ssh.exec_command('uname -s')
print stdout.read()

While there are a few more steps involved, doing it this way allows you to leverage the SSH layer directly, as opposed to using subprocess to spwan another Python instance, or figuring out the Fabric API. 虽然还有一些步骤涉及,但这样做可以让您直接利用SSH层,而不是使用subprocess进程来spwan另一个Python实例,或者搞清楚Fabric API。 I have several projects, both web- and console- using Paramiko in this manner and I haven't had too much trouble. 我有几个项目,包括网络和控制台 - 以这种方式使用Paramiko,我没有遇到太多麻烦。

Paramiko is extensively documented . Paramiko有广泛的文献记载

# thanks to aaron, extending his code a little more
# here is a little bit more of a graceful solution than running subprocess.call, and specifying multiple hosts

from fabric.api import env, run

def main():
    run("uname -a")

def setup():
    env.hosts = ['host0','host1']

if __name__ == '__main__':
    setup()
    for host in env.hosts:
        env.host_string = host
        main()

Since 1.5.0 there is a way better way to do this than messing around with argv. 1.5.0开始,有一种更好的方法来做到这一点,而不是乱搞argv。

import fabric.main

def main():
    fabric.main.main(fabfile_locations=[__file__])

if __name__ == "__main__":
    main()

This can also be utilized as a console script in setup.py 这也可以用作setup.py中的控制台脚本

This isn't a really nice solution, but will work: 这不是一个非常好的解决方案,但可以工作:

import subprocess

def hello():
    print 'Hello'

if __name__ == '__main__':
    subprocess.call(['fab', '-f', __file__, 'hello'])

I fine tuned the above example to past through argv arguments you might want to pass to local commands and specify an optional default_commands list instead of a hard coded command name. 我很好地调整了上面的示例,通过argv参数,您可能希望传递给本地命令并指定可选的default_commands列表而不是硬编码的命令名称。 Note, the filename must have a .py extension or fab will not detect it as a fab file! 请注意,文件名必须具有.py扩展名,否则fab将不会将其检测为fab文件!

#!/usr/bin/env python
from fabric.api import local

default_commands = ['hello', ]

def hello():
    print ('hello world')

def hostname():
    local('hostname')

if __name__ == '__main__':
   import sys
   from fabric.main import main
   sys.argv = ['fab', '-f', __file__,] +  default_commands + sys.argv[1:]
   main()

docs.fabfile.org/en/1.4.0/usage/library.html docs.fabfile.org/en/1.4.0/usage/library.html

"As that section mentions, the key is simply that run, sudo and the other operations only look in one place when connecting: env.host_string . All of the other mechanisms for setting hosts are interpreted by the fab tool when it runs, and don't matter when running as a library." “正如该部分提到的,关键只是运行,sudo和其他操作只在连接时查看一个地方:env.host_string。所有其他设置主机的机制在运行时由fab工具解释,并且不要在作为图书馆运作时很重要。“

I was looking at this same problem when I found this. 当我发现这个时,我正在看同样的问题。 Also, while looking I recall mention that when used in a fabfile, env changes should not be in the same def as run, sudo. 此外,虽然看起来我记得提到,当在fabfile中使用时,env更改不应该与run,sudo相同。 Who knows if this still applies when used in "library" mode. 谁知道在“库”模式下使用时是否仍然适用。

EDIT: Here is an example of said implementation 编辑:这是所述实施的一个例子

from fabric.api import env, run

def main():
    run("uname -a")

def setup():
    env.host_string = "me@remoteHost"

if __name__ == '__main__':
    setup()
    main()

Add this to the bottom of your fab file. 将其添加到fab文件的底部。

if __name__ == '__main__':
  from fabric.main import main
  import sys

  sys.argv = ['fab', '-f', __file__] + sys.argv[1:]

  main()

This is my modified version of Greg's answer that changes default behavior to show available commands instead of listing tons of fabric options. 这是我对Greg的回答的修改版本,它改变了默认行为以显示可用命令,而不是列出大量的结构选项。

if __name__ == '__main__':
    # imports for standalone mode only
    import sys, fabric.main

    # show available commands by default
    if not sys.argv[1:]:
        sys.argv.append('--list')

    fabric.main.main(fabfile_locations=[__file__])

I found the solution indirectly on run fabric file renamed other than fabfile.py and password-less ssh 我发现间接运行结构文件的解决方案已重命名为fabfile.py和无密码ssh

def deploy():
    ...

if __name__ == '__main__':
    from fabric import execute
    execute(deploy)

This way also work if your file doesn't have .py extension. 如果您的文件没有.py扩展名,这种方式也可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM