Fabric: 远程 Python 执行钩子

创建于 2011-08-19  ·  28评论  ·  资料来源: fabric/fabric

描述

最终只是一个占位符,如果人们需要该功能并且它很容易集成/集成有意义,而不是仅仅说“自己做,它只是 Python”——我们应该考虑让利用工具轻松执行远程 Python /RPC。 现代有用的候选人包括:

  • 执行网

    • 积极开发但可能只支持 Python 到 3.4?

    • 传输是 popen(本地)、ssh(通过二进制 😒)或直接套接字(带有引导远程脚本/服务器 in-repo)

    • 序列化是完全手动的,使用struct

    • 用于分布式pytest,因此至少经过了一些实战测试

    • 如果缺少明确的现代风格 API 文档(似乎只是示例/散文驱动?),API 相对健全(网关和通道对象、发送/接收、可用的轻度异步)

  • 火焰兵(4)

    • 积极开发,似乎至少支持 3.6,如果不是也支持 3.7

    • 使用名为serpent的基于 AST 的独立库进行序列化(在其 README 中明确说明了它存在的原因以及 Pyro 不使用 XML、JSON、Pickle 等的原因)

    • 使用 TCP/IP、Unix 套接字进行传输,并且可以选择使用 SSL/TLS

    • 非常有特色,包括在调用者端引发远程异常、自动处理重新连接等

    • 漂亮干净的 API(可以理解,在高层次上,类似于 execnet 的 re: 表示远程解释器的对象,如果感觉更现代一些),包括使用装饰器声明 RPC 调用的选项

  • 有丝分裂原

    • 积极开发(维护者在下面的评论中),至少支持 Python 3.6

    • 不幸的是,序列化 w/ pickle ,尽管有理由

    • 传输:实际上不是 100% 确定,但感觉就像直接套接字连接与每个 Mitogen 子节点能够在拓扑中向前路由请求相结合?

    • 比较有特色,而且它确实有的功能都是非常强大的

    • 即使远程端没有可用磁盘空间等也可以运行 - 整洁!

    • 花式来电端模块转发; 不确定其他选项是否/如何处理非标准库导入。

    • 远程端日志记录模块调用自动转发回调用者

    • 与一般的 Fab 单节点/兄弟节点列表用例不太直接相关:对子进程树、无头树和其他拓扑策略的一些非常简洁的强调

    • 只要远程端有 SSH 和 Python,就会自动引导,并且不需要先传输文件(与例如需要使用远程脚本的 execnet 相比)

    • API 比 Pyro/execnet 稍微复杂一些(大约多 1 层对象),但考虑到它的附加功能/布局,不一定是坏的方式

  • IPython 的内核端

    • 积极维护(有过吗!)

    • 使用 ZMQ 在某些客户端和 jupyter/ipython 内核进程之间进行传输

    • 使用 JSON 序列化,或者使用 msgpack/pickle

可能不可行但值得跟踪的选项:

  • Pushy (链接到专门讨论与 Fabric 集成的博客条目)_- 自 2016 年以来不受支持/存档,尽管在下文中,作者早些时候表达了合作兴趣_
  • Salt _- 远程(双关语不是有意的)机会人们可以尝试重用 salt 的 ZMQ 驱动的远程执行位,但一眼看去,它们似乎并没有以可重用的方式或任何方式被分解_
  • Celery _- 类似于 salt re:高级 pub/sub/message-passing arch 并且需要尝试提取较低级别的流,除了需要代理/队列系统(与 ZMQ 相比,它可以进行直接套接字到套接字样式的连接)所以即使不太可行?_
  • (Python wiki 项目列表)_- 最后一次扫描是在 2019 年初,所有明显有用的候选者都已经被删除_

我认为主要的吸引力是将您的 Fabric 主机/用户/等设置连接到这样的工具中。 所以可能更像是我们的 Django 贡献,而不是核心集成(特别是因为许多用户可能没有远程使用 Python,所以我们绝对不想_要求_使用这样的工具)。


Pushy 的作者还提到了在 Fabric 中使用他的工具作为 Paramiko 之上的潜在层的可能性; 我想同样的方法也可以应用于其他工具。

不完全确定这是否是一个好方法; plus 是与 SSH 的最终解耦; 减号是,嗯,我们在很多方面都非常特定于 SSH(并且使用了很多核心的 Paramiko 东西),我不认为这值得失去关注。


最初由Jeff Forcier ( bitprophet ) 于2010-09-20美国东部时间上午11:43提交

关系

  • 被 #246 复制:能够轻松地远程执行小的 Python 代码片段(而不是 shell 命令)
Core Feature Needs investigation Network

所有28条评论

肖恩·海耶斯(Sean_Hayes) 发布:


我在 GitHub 上创建了一个分支: https ://github.com/SeanHayes/fabric

在 fabric.decorators 中,我添加了一个名为 runs_on_remote 的装饰器。 这有点像穷人的远程处决。

基本上,当你用它包装一个函数时,如果 env.hosts 不为空,装饰器将在主机上运行'fab func_name',而不是允许函数在本地执行。 例如:

from fabric.api import *

env.hosts = []

def remote():
    env.hosts = ['your_host']

@runs_on_remote(remote_fabfile_path='/path/to/fabfile/dir/')
def foo():
    print local('ls /')

在本地运行“fab remote foo”将导致“fab foo”在“your_host”上运行。


美国东部时间2011年 1 月 16 日晚上 8 点 27 分

这方面的任何进展。 使用织物一段时间后,我认为这是最大的缺失部分之一。 能够在纯 Python 中编写远程实用程序方法当然可以更轻松地编写远程任务。

没有评论 == 没有进展,抱歉 :) 这对大多数用户来说并不是一个巨大的障碍——大多数人基本上都对 shell 脚本感到满意。 因此,虽然这_绝对_在“值得拥有”列表的顶部附近,但它仍然在“值得拥有”列表中。

我希望当我们开始组织 2.x 版时(如果不是更早的话,在接下来的几个月中的某个时间),它会得到更仔细的了解,因为那是让“在 Y 位置做 X”成为更抽象操作的好时机。

可能值得考虑的一种简化是使在远程系统上运行临时 python 脚本成为可能。 我什至考虑过手动执行此操作,方法是制作一个“remote_utils.py”文件或我在启动时放入远程系统的文件,然后使用我想在模块中运行的函数的名称调用该脚本。

假设您的意思是某种形式的“将本地 .py 复制到远程系统,执行它,然后可能再次删除它”,是的,偶尔也会被踢。 (甚至可以查看上面的一些评论。)

但这不需要核心支持,因此它可能属于一个本地代码库或例如Patchwork

我只想指出已经有一个库,从“sshuttle”派生出来,它实现了这个:

Remote Exec 允许您将 python 代码发送到远程机器并在那里运行,而无需在服务器上安装除标准 Python 解释器之外的任何东西。

它使用 SSH 连接到远程主机,发送您指定的 python 文件,在服务器上编译它们,并将控制权传递给指定的 main 函数。

此外,客户端安排服务器端的标准输入/标准输出连接到客户端的网络套接字,这样您就可以与上传的服务器二进制文件进行通信,就像您正常连接到它一样。

https://bitbucket.org/danderson/py-remoteexec

也就是说,原始代码(因此,fork 也是)是 GPLv2 许可的,我不确定作者是否愿意重新许可它。

@bitprophet我也在想这可能是一个本地扩展模块。 我只是还没有找到一个可以复制和改进的好的实现。 如果有人知道,我很想看看并尝试一下。

@abierbaum检查#461 中列出的库,我敢打赌其中至少有一个可能对此有一些实现。

幻想实现在任何 python 函数上都只有一个@remote装饰器,当被调用时,实际函数在远程目标上运行。 在指出的库中,execnet 似乎是最好的,但也是最复杂的。 (只是跳过文档)。

各种“将代码放在服务器上并运行它”的方法似乎并没有增加很多价值,而不仅仅是对文件进行“放置”,sudo 运行它,然后删除它。 更不用说这个方法允许你运行任何代码,而不仅仅是 Python 代码。

如果它运作良好,这对我来说真的很有帮助。 例如,我喜欢使用 _psutils_ 之类的东西来操作进程,而不是现在必须使用的 ps > grep > awk > kill 方法。

如果有人想要实现这一点,你最有可能采用什么方法?

为什么不只是

print run("""python -c 'import re
m = re.search("1", "m1m")
print m'""")
[localhost] run: python -c 'import re
m = re.search("1", "sfsdf1231231231dfads")
print m'
[localhost] out: <_sre.SRE_Match object at 0x1086cd8b8>

实际上,我不久前将解决方法(放置、运行、删除)添加到 Patchwork, https://github.com/fabric/patchwork/blob/master/patchwork/commands.py#L11 - 这是初稿,所以可以使用我敢肯定,有时会有一些爱。

如果您的函数是自包含的,这可以完成工作,因此您需要在函数体中导入。

def rpc(f):
    @wraps(f)
    def wrapper(*l, **kw):
        c = 'python -c "import marshal,pickle,types;types.FunctionType(marshal.loads(%r),globals(),%r)(*pickle.loads(%r),**pickle.loads(%r))"'
        c = c % (marshal.dumps(f.func_code),f.func_name,pickle.dumps(l),pickle.dumps(kw))
        run(c)
    return wrapper

例子:

<strong i="9">@task</strong>
<strong i="10">@rpc</strong>
def f(): print 1+1

工作正常,但在 bash 转义机制中序列化长函数时,fabric 失败。
Fabric 的设计是完全有缺陷的,因为它的 api, run(string) 意味着转义。
正确的运行 api 应该是 run(cmd=[]) 其中 cmd 是一个列表。
Fabric 不应转义,但必须使用序列化和 execv 而不是 exec /bin/sh -c 字符串。
可以支持 run(string) 但不鼓励使用它。

如果 ssh 不支持 execv char *const argv[],那么应该在远程端使用一个小助手,我们可以在 python 或 perl 中做这个助手。 这个助手也可以像上面的例子一样支持 python rpc

所以我尝试了上面@antonylesuisse 的建议,但遇到了一些问题。 无论出于何种原因,我都无法直接导入模块,即使我在尝试访问它们时使用 exec 在远程端导入了它们,解释器也会出现段错误。 看起来这可能是由于我运行了不同版本的 python,而实际运行结构的 python 版本位于 miniconda 环境中。

以下是一些放置源代码的函数,在对参数进行酸洗/取消酸洗后执行它,然后直接从输出文件通过线路获取酸洗响应。 我认为这应该避免任何外壳转义问题..当然,响应仍然必须是可腌制/不可腌制的,但只要它们似乎工作正常。

附上一个示例脚本。
rpc_example.py.zip
.
这仍然不是交互式的,但至少您可以使用它运行非交互式代码。 有没有人潜入 execnet 或 Pushy 集成?

@raddessi似乎Chopsticks可能是您正在寻找的图书馆。

我用筷子之类的织物。 我认为这很简单。
2017 年 8 月 18 日星期五 14:23:20 +0000 (UTC)
Fabien Meghazi [email protected]已写入:

@raddessi看来
筷子可能是
您正在寻找的图书馆。

https://mitogen.readthedocs.io/en/latest/是这里的新人,虽然我不记得上面列出的其他人是如何工作的,但这个人实际上引导了一个远程的内存中 Python 解释器(不需要远程安装 Python;使用 SSH - 但不是 Paramiko,sob)并将代码推送到其中执行。

它显然还可以强制子进程使用 SSH 的本地进程,这让它可以做诸如 SFTP-over-sudo 之类的事情(我不太了解它是如何工作的,但还没有阅读源代码。)

但是它不是 Python 3 兼容的,并且声称在那里没有计划,因此可能是一个障碍,因为 Fabric 2 / Invoke 是明确的 2+3 兼容的。

@bitprophet “Mitogen 是一个用于编写分布式自我复制程序的 Python 库。” 这个真的合适吗。 为什么不是 Ansible? 你看过 Ansible 吗? 我很好奇你的想法。 我们从织物换成盐,但我对它不是 100% 满意。 我想我下次会使用 Ansible。

不久前我检查了 Salt 和 Ansible,但两者都不喜欢。 也就是说,我认为 Fabric 与那些“完整”的配置管理系统大部分是正交的,所以这并不是一个公平的比较。 (比如说,使用 Fabric,你可以达到 75-85% 的效果,很多人都会这样做,我想尽可能地改进它——但 Fabric 将永远是一个自下而上的构建块类型库而像 Salt/Ansible/Chef/Puppet 这样的大多数 CM 工具更像是自上而下的框架。)

@bitprophet谢谢你的回复。

我对盐不满意,我对织物不满意。

Fabric 有时就像“远程 shell 执行”。 几年前我从 shell 脚本切换到 python,因为我喜欢回溯和异常。 在我的上下文中,类似 shell 的执行(错误写入 stdout/stderr 并继续下一行)是不可接受的。 我更喜欢未捕获的异常而不是“错误继续”,尤其是在生产系统中。

织物感觉像是退了一步。

我们用过几次,但改用盐。

但是盐太复杂了。

在我的团队中,大多数开发人员都对 salt 表示敬意。

这与织物不同。

我坐在椅子之间。

到目前为止,我还没有尝试过 Ansible。 但这似乎更简单,这对我很重要。

我希望下面的话不会伤害你。 ...我想我不会切换回织物。

对我来说,我认为结构是一个远程执行工具。 SaltStack/Ansible/Puppet/Chef 是一种状态管理平台。 目标不同。
Fabric 提供了一种直接的方式来管理远程主机。 有一些库为 Fabric 提供了一批代码片段。 这是“状态管理”的方向。
如果我们希望 Fabric 解决更复杂的远程执行问题,它要求用户编写他们的组件来处理连接或其他人员。 丝裂原适合这种情况。

在我的上下文中,类似 shell 的执行(错误写入 stdout/stderr 并继续下一行)是不可接受的。 我更喜欢未捕获的异常而不是“错误继续”,尤其是在生产系统中。

公平地说,Fabric 不应该继续出错,所以如果你看到了,那就是其他事情发生了。

也就是说,它仍然不像我们想要的那样干净的异常(基本上所有错误都会导致 SystemExit),并且版本 2 正在构建为对异常更加友好(SystemExit 仅在程序。)

@bitprophet ,请注意 Python 3 对 Mitogen 的支持现在是一个更明确的目标。 它不应该需要超过几周的时间,而且无论如何都需要在即将发布的 Fedora 版本上支持 Ansible。

@bitprophet ,另一个说明 Python 3 已经很长时间(loooong)最后达到了 master,结果将在 PyPI 上作为第一个稳定的系列版本在明天晚上之前发布。 'fakessh' 支持目前已被破坏且不在范围内,但我很想坚持修复它,并将其推广到 TCP/UDP/管道转发——希望在我落后于我的 Python 3 低迷之后,能量会回来现在很多新东西会很快发生:)

太棒了,很高兴听到它@dw! 我不知道什么时候有时间看看我的 Mitogen 集成,但是现在解释器版本的障碍已经消失了,这让我非常激动👍

@bitprophet 对此有何更新?

@bitprophet这个特性对我们的目的(远程调试)非常有用,很乐意以任何可能的方式帮助实现。

我刚刚发现了 mitogen,我认为这将是一个很好的面料后端。

事实上,我认为它可以有利地取代很多结构代码(也可能是大部分 pyinvoke)。 它消除了fabric/invoke(ssh/local)之间的“特殊情况”区别,并将所有这些合并到一个神奇的“上下文”中,该上下文也适用于“sudo”等后端,比fabric(恕我直言)更透明。

现在我真的感觉到面料中缺少这个功能的痛苦。 我正在考虑在远程端实现越来越复杂的业务逻辑。 现在这涉及使用sftp来回传输文件以确保正确设置,这有点笨重。 远程执行会好很多:只需打开文件、查找内容、搜索/替换等变得更加直观。

它还使得编写可在结构之外重用的 Python 代码成为可能。 现在我真的不能这样做,除非我真的很努力地眯着眼睛,因为从根本上说,python 代码只在本地运行。 所以我需要在主机之间来回复制文件(或进程?!)来做我需要的事情。 这远非理想...

现在我正处于一个交汇点:要么我继续走结构路线,要么我只是将我所有的代码移植到 mitogen 并在它周围制作一个小的执行器包装器。我没有足够地使用fabfile功能保证结构的复杂性,而 mitogen 为我的主要用例(即从异构环境中引导和恢复服务器)提供了更强大的功能......

但我知道,fabric 和 invoke 当然还有其他用例。 我只是觉得编写本机 python 代码会更自然,即使是 Fabric 中的现有功能(如代码执行),因为它会使错误处理、管道控制和现有反射或多或少正常工作......

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

相关问题

SamuelMarks picture SamuelMarks  ·  3评论

26huitailang picture 26huitailang  ·  3评论

jamesob picture jamesob  ·  3评论

Grazfather picture Grazfather  ·  4评论

bitprophet picture bitprophet  ·  4评论