3

自分の Python スクリプト内でライブラリとして使用すると、ファブリックが機能しません。fabfile.py私の問題を示すために、非常に短い例を作成しました。

#!/usr/bin/env python

from fabric.api import *

print("Hello")

def test():
    with settings(host_string='myIp', user="myUser", password="myPassword"):
        run("hostname")

if __name__ == '__main__':
   test()

ランニングfabは魔法のように機能します。

$ fab test
Hello
[myIp] run: hostname
[myIp] out: ThisHost
[myIp] out:


Done.
Disconnecting from myUser@myIp... done.

さて、fab なしで python スクリプトを実行すると、どこかで壊れているようです。

$ python fabfile.py
Hello
[myIp] run: hostname

すぐに戻ってくるので、応答を待っているようにも見えません。エラーがあるかもしれませんが、それらを出力する方法がわかりません。

vagrant 仮想マシン内でこのスクリプトを実行しています。エラーなしで実行されるので、これfabは問題ではないと思います。

アップデート

最初のrun. local一方、動作します!

同僚のラップトップでスクリプトを実行しましたが、問題なく実行されました。Ubuntu 10.04 でファブリック 1.5.1 を使用して Python 2.6.5 を使用しているため、これには問題があると思います。これを適切にデバッグする方法はありますか?

4

2 に答える 2

2

同様の問題が発生しました。 fab コマンドはエラーなしで終了しましたが、最初のrun()/sudo()コマンドに空白行があるだけです。

run()そのため、コマンドを try: except: ブロックに入れて、トレースバックを出力しました。

def do_something():
    print(green("Executing on %(host)s as %(user)s" % env))
    try:
        run("uname -a")
    except:
        import traceback
        tb = traceback.format_exc()
        print(tb)

fabfile/network.pyEOFError または TypeError をキャッチしたときに、スクリプトが 419 行目で終了したことがわかりました。スクリプトを次のように変更しました。

...
except (EOFError, TypeError) as err:
    print err
    # Print a newline (in case user was sitting at prompt)
    print('')
    sys.exit(0)
...

次に印刷されました:

connect() got an unexpected keyword argument 'sock'

そのため、数行上にある connect メソッドの sock キーワード引数を削除すると、魅力的に機能しました。paramikosock キーワードを許可しないバージョンの問題だと思います。

バージョン:

Python 2.7.3
Fabric >= 1.5.3
paramiko 1.10.0
于 2013-03-08T14:04:55.430 に答える
1

fab コマンドを見ると、次のようになります。

sys.exit(
   load_entry_point('Fabric==1.4.3', 'console_scripts', 'fab')()
)

これは、Fabric パッケージの entry_points.txt というファイルで console_scripts というラベルの付いたブロックを探し、そこにリストされているメソッドを実行することを意味します。この場合は fabric.main:main

このメソッドを見ると、引数の解析、興味深い fabfile のインポート、そして次のことがわかります。

if fabfile:
    docstring, callables, default = load_fabfile(fabfile)
    state.commands.update(callables)
....
for name, args, kwargs, arg_hosts, arg_roles, arg_exclude_hosts in commands_to_run:
    execute(
            name,
            hosts=arg_hosts,
            roles=arg_roles,
            exclude_hosts=arg_exclude_hosts,
            *args, **kwargs
        )   

いくつかの実験で、次のようなものを思いつくことができます:

from fabric import state
from fabric.api import *
from fabric.tasks import execute
from fabric.network import disconnect_all

def test():
    with settings(host_string='host', user="user", password="password"):
        print run("hostname")

if __name__ == '__main__':
    state.commands.update({'test': test})
    execute("test") 

    if state.output.status:
        print("\nDone.")
    disconnect_all()

これは明らかに非常に不完全ですが、おそらく追加する必要があるのは

disconnect_all()

スクリプトの最後の行

于 2012-12-03T22:57:52.807 に答える