Python中的可行替代方案

2020-06-13 12:53:13

我的VPS(虚拟专用服务器)变旧了,运营它的公司宣布,下个月,我使用的促销活动将到期,现在运行它的费用将超过三倍。另外,我还想更新家里的其他机器,因为它们使用的是旧的Ubuntu。

这促使我寻求某种部署自动化,这样我就可以将我的基础设施指定为代码,理想情况下再也不会花太多时间使用它。

我不喜欢过度成长为脚本语言的基于YAML的配置语言。这是格林斯潘第十条规则的经典例子:

任何足够复杂的C或Fortran程序都包含半个Common Lisp的临时的、非正式指定的、充满错误的、缓慢的实现。

调试它是一场噩梦,IDE没有支持等等。

每次我尝试使用Ansible时的混乱感觉让我开始探索替代方案,最好是用python,它将定义食谱或任何简单的python代码。

几乎每一篇关于Python Ansible Alternative主题的文章都提到了织物。它看起来很棒,但看起来有点不同。它是用于在远程主机上运行命令的系统。这绝对是Ansible所做的工作的一部分,但我也想要某种抽象层。

>;>;>;def disk_free(C):.。uname=c。运行(';uname-s&39;,Hide=True).。如果Linux';在uname中。标准输出:.。命令=";df-h/|ail-n1|awk';{打印$5}';";.。返回c。Run(COMMAND,HIDE=True)。STDOUT(标准)。条带().。错误=";不知道如何获取{}!";上的磁盘空间。格式化(未命名).。提升出口(错误)

我的意思是,我不想手动运行apt install nginx,然后解析输出并尝试决定命令是否成功运行(我以前用paramiko做过,相信我,这并不有趣)。

我想要稍微高级一点的东西,它可以为我解析标准实用程序,理想情况下支持多操作系统,这样当我决定使用CentOS而不是我现在使用的Ubuntu服务器时,它可以为我处理不同的实用程序。

从Fabric.api导入*从Fabtools导入需要导入Fabtools@task def setup():#需要一些Debian/Ubuntu包需要。黛比。Packages([';imagemagick';,';libxml2-dev';,])#需要带有Fabtools的Python包。蟒蛇。viralenv(';/home/myuser/env';):必需。蟒蛇。包(#39;金字塔#)#需要电子邮件服务器要求。后缀。server(';example.com';)#需要PostgreSQL服务器要求。波斯格雷斯。server()需要。波斯格雷斯。用户(';myuser';,';s3cr3tp4ssw0rd';)需要。波斯格雷斯。数据库(#39;myappsdb&39;,#39;myuser&39;)#需要针对我们的应用程序要求的主管进程。主管。进程(';myapp';,command=';/home/myuser/env/bin/genicorn_paster/home/myuser/env/myapp/Production.ini';,directory=';/home/myuser/env/myapp';,user=';myuser';)#需要代理我们的应用程序所需的nginx服务器。恩吉克斯。PROXED_SITE(';example.com';,docroot=';/home/myuser/env/myapp/myapp/public&39;,proxy_url=';http://127.0.0.1:8888';)#设置每日cron任务。克伦。添加_DAILY(';维护';,';myuser';,';my_script.py';)。

上一次提交是在9个月前,有78个未解决的问题,28个等待的拉取请求,支持的操作系统列表已经很古老了:

从Fabrix.api导入IS_FILE_NOT_EXISTS,yum_INSTALL从Fabrix.api导入EDIT_FILE,EDIT_INI_SECTION,REPLACE_LINE DEF INSTALL_PHP():if is_FILE_NOT_EXISTS(";/etc/yum.repos.d/epel.repo";):YUM_INSTALL(";https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm";如果文件不存在(";/etc/yum.repos.d/remi-php70.repo";):百胜安装(";https://rpms.remirepo.net/enterprise/remi-release-7.rpm";)编辑文件(";/etc/yum.repos.d/remi-php70.repo";,edit_ini_Section(";[remi-php70]";,REPLACE_LINE(";Enabled=0";,";Enabled=1";))yum_install(";";";php-cli php-common php-fpm php-gd php-mbstring php-mysql php-pdo php-pear php-ecl-imagick php-process php-xml php-opcache php-mcrypt php-soap&#。

这对我来说有点好笑,因为我前段时间和帕拉米科创造了一些非常相似的东西。

它看起来也死了,只有204个提交和一个贡献者,上一次提交是在15个月前。我不想把我的系统建立在已经死了的东西上。

Pyinfra看起来很有希望,而且还没有死:2233次提交,14个贡献者,最后一次提交是在昨天。这就是我要说的!

示例完全按照我的要求工作;声明性语言,重要的参数是参数,而不是字符串。唯一奇怪的是将描述指定为集合,但无论如何,我可以看到这里的推理路线。

由于Pyinfra是唯一一种看起来没有死的东西,它可以做我想做的事情,所以这个决定并不难。那么,让我们试一试吧:

现在让我们试试hello world。我在端口上挣扎了一会儿,因为我使用非标准端口来隧道通过酒店和机场wifi,快速浏览一下可以帮助显示我应该使用--port参数:

$pyinfra kitakitsune.org--端口443 EXEC--ECHO";hello world";-->;正在加载配置.-->;正在连接到主机.。[kitakitsune.org]已连接-->;建议的更改:取消分组:[kitakitsune.org]操作:1命令:1-->;开始操作运行.-->;开始操作:服务器/Shell(u';echo hello world';,)[kitakitsune.org]hello world[kitakitsune.org]成功-->;结果:取消分组:[kitakitsune.org]成功:1。

看上去不错。让我们尝试为虚拟Ubuntu服务器创建一个更复杂的部署,这是我不久前在VirtualBox中创建的。我对inventory.py文件有点费劲,但是后来我在文档中找到了正确的参数:

-->;正在加载配置.-->;正在加载清单.-->;正在连接到主机.。[192.168.0.106]已连接-->;正在准备操作.。加载:ployment ment.py[192.168.0.106]Ready:ployment.py-->;建议的更改:组:My_Hosts/Inventory[192.168.0.106]操作:1命令:1-->;开始操作运行.-->;启动操作:服务器/Shell(';echo";hello world";';)[192.168.0.106]>;>;sh-c'。';[192.168.0.106]hello world[192.168.0.106]成功-->;结果:组:My_Hosts/Inventory[192.168.0.106]成功:1错误:0命令:1/1。

-->;启动操作:服务器/Shell(';echo";hello world&34;';,)[192.168.0.106]>;>;>;sudo-S-H-nsh-c&39;echo";hello world";';[192.168.0.106]sudo:需要密码[192.168.0.106]错误-->;pyinfra错误:否。

我在谷歌上搜索并查看了文档和源代码,但看起来没有办法指定sudo密码,我觉得这非常奇怪。有人甚至在前一天制造了一个问题:

看起来不支持带密码的sudo。因此,我已经通过更改行在/etc/sudoers中禁用了sudo密码。

-->;正在加载配置.-->;正在加载清单.-->;正在连接到主机.。[192.168.0.106]已连接-->;正在准备操作.。加载:ployment ment.py[192.168.0.106]Ready:ployment.py-->;建议的更改:组:My_Hosts/Inventory[192.168.0.106]操作:1命令:1-->;开始操作运行.-->;启动操作:服务器/Shell(';echo";hello world";';)[192.168.0.106]>;>;sudo-S-H。Hello world";';[192.168.0.106]hello world[192.168.0.106]成功-->;结果:组:MY_HOSTS/Inventory[192.168.0.106]成功:1错误:0命令:1/1。

让我们来尝试一些更复杂的方法--设置一台nginx服务器并为其上传正确的配置文件:

而且它是有效的,只有一个例外,那就是解析输出(是的,这就是解析糟糕的原因):

回溯(最近一次调用):文件";src/gevent/greenlet.py";,第854行,在gevent中。_gevent_cgreenlet.Greenlet.run文件";/home/bystrousak/.local/lib/python2.7/site-packages/pyinfra/api/util.py";,第471行,在READ_BUFFER_PRINT(行)文件";/home/bystrousak/.local/lib/python2.7/site-packages/pyinfra/api/util.py";中。第455行,in_print line=Print_Func(Line)文件";/home/bystrousak/.local/lib/python2.7/site-packages/pyinfra/api/connectors/util.py";,行61,in<;lambda>;print_func=lambda line:';{0}{1}';.format(print_prefix,line),UnicodeEncodeError:';ascii';编解码器可以';\u2192';t编码字符u';\u2192';在位置74:序号不在范围内(128)2020-06-11T23:55:28Z<;0x7fde3f4dd6b0处的Greenlet:Read_Buffer(';stdout&39;,<;paramiko.ChannelFile from<;paramiko.Channel 2(OP;队列在0x7fde39f60f30队列=deque([(';stdout';结果:组:My_Hosts/Inventory[192.168.0.106]成功:1错误:0命令:1/1。

这也很奇怪,但我可能使用捷克语本地化,所以我并不感到惊讶。

-->;正在加载配置.-->;正在加载清单.-->;正在连接到主机.。[192.168.0.106]已连接-->;正在准备操作.。正在加载:deployment.py已加载事实Deb_Packages[192.168.0.106]Ready:deployment.py-->;建议的更改:组:My_Hosts/Inventory[192.168.0.106]操作:1命令:1-->;开始操作运行.-->;开始操作:APT/Packages(';nginx';,u';update=True';,u';Present=True';)。sudo-S-H-nsh-c';apt-get update';[192.168.0.106]HIT:1 http://archive.ubuntu.com/ubuntu Bionic InRelease[192.168.0.106]HIT:2 http://archive.ubuntu.com/ubuntu Bionic-Updates InRelease[192.168.0.106]HIT:3 http://archive.ubuntu.com/ubuntu Bionic-Backports InRelease[192.168.0.106]HIT:4 http://archive.ubuntu.com/ubuntu Bionic-Security InRelease[192.168.0.106]正在读取包列表.。[192.168.0.106]成功-->;结果:组:My_Hosts/Inventory[192.168.0.106]成功:1错误:0命令:1/1。

我真的很喜欢金丝雀。它有它的怪癖,但它们只是一些小烦恼,不像我在其他产品中发现的大烦恼,比如Ansible。但与Ansible不同的是,它易于理解、易于使用,而且它使用的是Python,我知道并喜欢Python,而且我的IDE可以提供自动补全和调试器,这与其他基于YAML的领域特定语言不同。

模块导入文件sudo=True apt,从pyInfrastructure导入apt。模块从pyInfrastructure导入init,导入文件sudo=True apt。软件包(';nginx&39;,update=True,Present=True)文件。将(';configs/nginx.conf';,';/etc/nginx/nginx.conf';,user=';root';,group=';root';,mode=';644';,)初始化。systemd(';nginx';,Running=True,Restarted=True,Enabled=True,)。

改变了关于Ansible的激烈语气,因为这不是重点。添加了关于VS Code Ansible插件的标注。

是的,我的英语可能很糟糕,但这类博客帖子还不符合(付费)语法更正的资格(队列中有优先级更高的东西)。如果你想改变这一点,请订阅“我的守护神”(My Patreon)。即使每月只有1美元,你也可以有所作为。