Fabric
Fabric学习 [toc] 总结 fabric3 移除了很多实用的功能和装饰器,变得更精简了,另外fab这个cli入口提供的参数能力也变弱了,目前个人实用的方式是typer+fabric3+makefile: typer 作为参数解析入口 makefile 固定一些操作逻辑,可以使用它的并发操作,而不是ThreadingGroup Link Welcome to Fabric! Welcome to Invoke’s documentation! 使用 Fabric 自动化部署 What is Fabric python的一个high level的库,通过ssh执行shell命令。 基于以下两个包构建的: Invoke,subprocess command execution and command-line features Paramiko,SSH protocol implementation 私钥配置 配置ssh的authorized_keys,将本机的id_rsa.pub信息复制到远程的authorized_keys文件中 简要用法 pty(prompt by hand),如果sudo有密码,那么用pty来手动输入 >>> from fabric import Connection >>> c = Connection('192.168.9.139') >>> c.run('sudo useradd mydbuser', pty=True) [sudo] password: <Result cmd='sudo useradd mydbuser' exited=0> >>> c.run('id -u mydbuser') 利用Invoke的自动回应来输入sudo密码,注意pattern的正确匹配,以及repsonese的结尾符号 >>> from invoke import Responder >>> from fabric import Connection >>> c = Connection('host') >>> sudopass = Responder( ... pattern=r'\[sudo\] password:', ... response='mypassword\n', ... ) >>> c.run('sudo whoami', pty=True, watchers=[sudopass]) [sudo] password: root <Result cmd='sudo whoami' exited=0> watchers虽然提供了自动填充密码的功能,但是代码中多次引用这种配置比较麻烦,所以考虑将sudopass的内容放入配置里面,让Connection.sudo来处理剩下的工作。 >>> import getpass >>> from fabric import Connection, Config >>> sudo_pass = getpass.getpass("What's your sudo password?") What's your sudo password? >>> config = Config(overrides={'sudo': {'password': sudo_pass}}) >>> c = Connection('db1', config=config) >>> c.sudo('whoami', hide='stderr') root <Result cmd="...whoami" exited=0> >>> c.sudo('useradd mydbuser') <Result cmd="...useradd mydbuser" exited=0> >>> c.run('id -u mydbuser') 1001 <Result cmd='id -u mydbuser' exited=0> 文件传输,transfer files,利用Connection.put和Connection.get。在使用时发现如果像下面这样定义remote的话,会报错OSError,要带上远程的文件重命名就不会报错。 >>> from fabric import Connection >>> result = Connection('web1').put('myfiles.tgz', remote='/opt/mydata/') >>> print("Uploaded {0.local} to {0.remote}".format(result)) Uploaded /local/myfiles.tgz to /opt/mydata/ 之前都是单行的操作,实际多半不是这样,多个同时执行,如上传、解压,路径、文件名可以作为参数传入,以便复用函数 from fabric import Connection c = Connection('web1') c.put('myfiles.tgz', '/opt/mydata') c.run('tar -C /opt/mydata -xzvf /opt/mydata/myfiles.tgz') def upload_and_unpack(c): c.put('myfiles.tgz', '/opt/mydata') c.run('tar -C /opt/mydata -xzvf /opt/mydata/myfiles.tgz') 多服务器的情况,这个单列出来 最直观的方法是遍历一个connection列表 >>> from fabric import Connection >>> for host in ('web1', 'web2', 'mac1'): >>> result = Connection(host).run('uname -s') ... print("{}: {}".format(host, result.stdout.strip())) ... ... web1: Linux web2: Linux mac1: Darwin fabric提供了一个更好的解决办法,把所有的对象放到一个Group里面。 Group和SerialGroup(Subclass of Group which executes in simple, serial fashion. New in version 2.0.) 返回的结果看,Connection返回单个的Result对象,Group返回GroupResult对象,dict-like In [18]: results = Group('peter@192.168.9.218', 'peter@192.168.9.208').run('uname -s') Linux Linux In [19]: for conn, result in results.items(): ...: print("{0.host}: {1.stdout}".format(conn, result)) ...: 192.168.9.218: Linux 192.168.9.208: Linux Group对象来执行的操作会对所有服务器生效,但是这里官方教程的pool.put会得到一个AttributeError: 'SerialGroup' object has no attribute 'put'错误,已在github提交issue from fabric import SerialGroup as Group pool = Group('web1', 'web2', 'web3') pool.put('myfiles.tgz', '/opt/mydata') pool.run('tar -C /opt/mydata -xzvf /opt/mydata/myfiles.tgz') fab cli tool 封装了Invoke的CLI功能,能够很快的在多个机器上运行tasks。 ...