Python fabric 2.3 sudo命令的并行执行
我正在尝试使用fabric 2.3在一些服务器上运行一些需要sudo的任务。我这里的主要目标是并行化操作,因此我考虑使用fabric api的Python fabric 2.3 sudo命令的并行执行,python,fabric,Python,Fabric,我正在尝试使用fabric 2.3在一些服务器上运行一些需要sudo的任务。我这里的主要目标是并行化操作,因此我考虑使用fabric api的ThreadingGroup类,但它不支持sudo 为了清楚起见,下面是我的代码 #!/usr/bin/env python from fabric import ThreadingGroup, Config from getpass import getpass sudo_pass = getpass("Enter your sudo passwo
ThreadingGroup
类,但它不支持sudo
为了清楚起见,下面是我的代码
#!/usr/bin/env python
from fabric import ThreadingGroup, Config
from getpass import getpass
sudo_pass = getpass("Enter your sudo password: ")
sudo_config = Config(overrides={'sudo': {'password': sudo_pass}})
server_pool = ThreadingGroup("test1", "test2",
config=sudo_config)
result = server_pool.sudo('cat /etc/shadow', hide='stderr')
print(result)
现在,这与上面提到的不一样,因为ThreadingGroup
不支持Connection
类支持的所有方法
我可以在多台服务器上运行sudo
,方法是迭代各个主机,然后为每个主机创建连接,但这并不高效
那么有没有一种方法可以让它与fabric 2.3平行呢?我也查阅了官方文件,但没有发现任何东西
此外,在官方文档之后,我对它进行了更多的测试,似乎ThreadingGroup
只有在如下方式运行时才能实现并行性
fabric.ThreadingGroup('test1','test2')。run('uname-s')
但是,如果您像下面这样运行它,它不会并行运行
def run_task(c):
c.run('uname -s')
for cxn in fabric.ThreadingGroup('test1', 'test2'):
run_task(cxn)
因此,到目前为止,fabric 2.3中似乎没有太多灵活的并行支持,我可能只能切换回fabric版本1。当前版本(到目前为止为2.4)中似乎没有实现某些功能。 一个可选的解决方案是在源文件中添加一些代码。 您可以找到fabric的安装路径,然后编辑group.py 首先,在group.py中添加此函数:
def thread_worker_sudo(cxn, queue, args, kwargs):
result = cxn.sudo(*args, **kwargs)
# TODO: namedtuple or attrs object?
queue.put((cxn, result))
然后在ThreadingGroup类中添加sudo函数:
class ThreadingGroup(Group):
.... original ThreadingGroup
def sudo(self, *args, **kwargs):
results = GroupResult()
queue = Queue()
threads = []
for cxn in self:
my_kwargs = dict(cxn=cxn, queue=queue, args=args, kwargs=kwargs)
thread = ExceptionHandlingThread(
target=thread_worker_sudo, kwargs=my_kwargs
)
threads.append(thread)
for thread in threads:
thread.start()
for thread in threads:
# TODO: configurable join timeout
# TODO: (in sudo's version) configurability around interactive
# prompting resulting in an exception instead, as in v1
thread.join()
# Get non-exception results from queue
while not queue.empty():
# TODO: io-sleep? shouldn't matter if all threads are now joined
cxn, result = queue.get(block=False)
# TODO: outstanding musings about how exactly aggregate results
# ought to ideally operate...heterogenous obj like this, multiple
# objs, ??
results[cxn] = result
# Get exceptions from the threads themselves.
# TODO: in a non-thread setup, this would differ, e.g.:
# - a queue if using multiprocessing
# - some other state-passing mechanism if using e.g. coroutines
# - ???
excepted = False
for thread in threads:
wrapper = thread.exception()
if wrapper is not None:
# Outer kwargs is Thread instantiation kwargs, inner is kwargs
# passed to thread target/body.
cxn = wrapper.kwargs["kwargs"]["cxn"]
results[cxn] = wrapper.value
excepted = True
if excepted:
raise GroupException(results)
return results
我只是复制函数run的代码并替换这一行
thread = ExceptionHandlingThread(
target=thread_worker, kwargs=my_kwargs
)
与
对我来说是这样的:
def test_sudo(group):
group.sudo('whoami', user='root')
$ python fabfile.py
root
root
root
root
root
但是,我不确定,它是否适用于所有情况。如果要以root身份运行所有任务,为什么不从一开始就使用sudo执行脚本?1)我不尝试以root身份运行所有任务,因为只有某些任务需要sudo。2) 在本地机器上以
sudo
的身份运行脚本如何在远程机器上授予sudo
?3) 如果我有另一组根本不需要sudo
的远程主机怎么办?您可以在/etc/sudoers
中为您的用户和该命令设置属性。这样,您就明确地将要在fabric
中运行的命令列为白名单,并且您的密码不会有泄漏的危险。@NilsWerner这与fabric根本没有关系,更与在系统本身上配置sudo有关。我的问题更多的是关于如何将sudo与新版本的fabric并行运行!!我不担心密码泄露,因为我使用getpass输入密码,密码或无密码是完全不同的问题。一旦密码提示消失,用server\u pool.sudo('cat/etc/shadow',hide='stderr')
替换为server\u pool.run('sudo cat/etc/shadow',hide='stderr')
。
def test_sudo(group):
group.sudo('whoami', user='root')
$ python fabfile.py
root
root
root
root
root