fabric: run() 无错误挂起
from fabric.api import env
from fabric.api import run
class FabricSupport:
def __init__ (self):
pass
def run(self, host, command):
env.key_filename = 'C:/.ssh/dev.pub'
env.host_string = "%s:%s" % (host, 22)
run(command, timeout=5)
fab = FabricSupport()
def execute(host, txt):
stdout = ""
try:
stdout = fab.run(host, txt)
except Exception, e:
stdout = str(e)
return stdout
result = execute("23.23.23.23", "uname -a")
它只是输出以下内容,然后一直保持这个状态,没有结束。超时似乎也没有起作用。如果能输出更多信息就好了,这样我可以调查一下发生了什么。
[12.45.241.11:22] 运行命令: uname -a
3 个回答
这周我在远程机器上运行一个需要很长时间的任务时,遇到了同样的挂起错误。
我通过在fabric.api.env配置中指定'keepalive'选项解决了这个问题。这个配置会让fabric每隔几分钟发送一个保持连接的消息。
http://docs.fabfile.org/en/1.14/usage/env.html#keepalive
我把这个值设置为30,这样在运行3个小时的任务时就不会挂起了。
今天我在使用Ubuntu的时候遇到了同样的问题。我的问题出在活动的shell设置上:
env.shell = /bin/sh -l -c
用这个shell的时候,脚本无法顺利执行远程命令,导致ssh连接挂掉。控制权一直停留在ssh的shell里,结果在fabric中出现了超时。
但是当我把设置改成:
env.shell = "/bin/bash -c"
一切就正常了。
总的建议是:根据你的操作系统检查一下shell和参数设置。
我不太清楚你这段代码的最终目的是什么。如果你想通过把它放在一个类里来隔离修改环境的影响,那是不行的。因为在fabric中,它是一个模块级别的全局变量,无论你在哪里修改它(就像你在这里做的那样),都会影响后面的代码。我觉得你可能真正想要的是这个:
from fabric.api import run, execute, task, settings
@task
def custom_runner(command):
"""Runs command with custom key_filename"""
with settings(warn_only=True, key_filename=r"C:\.ssh\dev.pub"):
result = run(command, timeout=5)
return result
result = execute(custom_runner, "uname -a", host="23.23.23.23")
请记住,这个代码不能直接被“fab”命令行工具使用,因为它会在fab加载fabfile时立即执行那段代码(result = execute...)。这只能作为库来使用。
你可以使用roledefs来处理一组主机。结果对象会是一个字典,每个主机都是一个键,对应的值是任务的返回对象。你几乎不想使用裸露的异常处理,Fabric有自己的一套方法来防止异常导致你的程序崩溃。