python的两种执行模式_python之fabric(二):执行模式(转)

执行模式:

执行模式可以让你在多个主机上执行多个任务。

执行策略:

默认fabric是单个有序地执行方法,其行为如下:

1. 创建一系列任务,通过fab任务执行要执行的任务;

2. 根据主机列表定义,去执行每一个任务;

3. 没有主机定义的任务,将在本地执行一次。

from fabric.api import *env.hosts= ['master','anhuitest']

env.user= 'root'env.key_filename= '/home/lemon/.ssh/id_rsa'

deftaskA():

run('ls')deftaskB():

run('whoami')#将在host1, host2都执行taskA, taskB

fab -f ./test.py taskA taskB

taskA executed on master

taskA executed on anhuitest

taskB executed on master

taskB executed on anhuitest

定义任务:

如何定义任务,详情可见这里。

定义主机列表:

大多数时候你都需要根据目标,来定义多个远程主机,而不是仅在本地。

主机:

python定义的主机字符串为:

username@hostname:port #用户名和端口都可以省略

主机定义也支持IPV6格式,如:

::1, [::1]:1222user@2001:db8::1user@[2001:db8::1]:1222

角色:

角色提供了可以定义一个字符串对应于一组主机列表,而不是每次都针对的是整个主机列表,如:

from fabric.api importenv#假如www1, www2, www3是你的web服务器, 你可以指定任务由特定的角色来执行

env.roledefs['webservers'] = ['www1', 'www2', 'www3']#定义多个角色

env.roledefs ={'web': ['www1', 'www2', 'www3'],'dns': ['ns1', 'ns2']

}

怎么构建hosts:

通过全局的env:

from fabric.api importenv, run

env.hosts= ['host1', 'host2']defmytask():

run('ls /var/www')

env配置会被每个任务检查,因此你完全可以在方法中设置env,如:

from fabric.api importenv, rundefset_hosts():

env.hosts= ['host1', 'host2']defmytask():

run('ls /var/www')#调用

fab set_hosts mytask, set_hosts

通过命令行参数指定:

fab -H host1,host2 mytask #会被env.hosts所重写,类似角色也可以通过-R role1, role2, ...来定义

你也可以扩展命令行定义的主机,如:

from fabric.api importenv, run

env.hosts.extend(['host3', 'host4'])defmytask():

run('ls /var/www')#那么执行主机将merge为host1,host2,host3,host4

fab -H host1, host2 mytask

NOTE: env.hosts是python的list对象,所以你可以用list.append()方法添加host,或者其他方法。

针对每个任务的命令行参数:这是fabric提供一种更细粒度的定制:

from fabric.api importrundefmytask():

run('ls /var/www')#该定义将重写其他任何hosts定义,mytask仅会在host1,host2上执行

fab mytask:hosts="host1;host2"

针对每个任务进行修饰:

from fabric.api importhosts, run

@hosts('host1', 'host2')defmytask():

run('ls /var/www')#或者

my_hosts = ('host1', 'host2')

@hosts(my_hosts)defmytask():#...

#这种修饰将重写env.hosts设置, 但不会重写上面通过命令行定义的任务。

总结下上面这些host与task绑定定义的优先级:

#由高到低

1. 命令行 fab mytask:host=host12. fabfile中修饰任务@hosts('host1')3. 在fabfile中设置env.hosts = ['host1']4. 在命令行中-H host1,host2,...

主机列表组合

from fabric.api importenv, hosts, roles, run

env.roledefs= {'role1': ['b', 'c']}

@hosts('a', 'b')

@roles('role1')defmytask():

run('ls /var/www')#若命令行不包含task定义,则上面的mytask家在a, b, c主机上执行

排除特定的主机

#若myrole被定义运行[host1, host2,...,host15], 则该命令将排除host2,host5

$ fab -R myrole -x host2,host5 mytask #该-x并不会修改env.hosts

用Execute智能地执行任务:

看这么一个例子:

from fabric.api importrun, roles

env.roledefs={'db': ['db1', 'db2'],'web': ['web1', 'web2', 'web3'],

}

@roles('db')defmigrate():#Database stuff here.

pass@roles('web')defupdate():#Code updates here.

pass

#在fabric1.2之前,我们需要fab migrate update来执行这两个任务,#在fabric1.2之后,我们可以通过execute函数来执行这两个任务:

from fabric.api importrun, roles, executedefdeploy():

execute(migrate)

execute(update)

通过Execute访问多主机的结果:

一个范例

from fabric.api importenv, roles, task, execute, run, runs_once

env.roledefs={'zoo': ['zooserver'],'mysql': ['mysqlmaster'],

}

@taskdefworkhorse():return run("uname -a")

@roles('zoo')

@task

@runs_oncedefgo():

results=execute(workhorse)printresults#执行

fab go

用Execute动态设置host列表:

我们可以通过传递参数,动态设置hosts,如:

from fabric.api importrun, execute, task#For example, code talking to an HTTP API, or a database, or ...

from mylib importexternal_datastore#This is the actual algorithm involved. It does not care about host#lists at all.

defdo_work():

run("something interesting on a host")#This is the user-facing task invoked on the command line.

@taskdefdeploy(lookup_param):#This is the magic you don't get with @hosts or @roles.

#Even lazy-loading roles require you to declare available roles

#beforehand. Here, the sky is the limit.

host_list =external_datastore.query(lookup_param)#Put this dynamically generated host list together with the work to be

#done.

execute(do_work, hosts=host_list)#调用

fab deploy:app

fab deploy:other

一个替代的方法:

from fabric.api importrun, taskfrom mylib importexternal_datastore#Marked as a publicly visible task, but otherwise unchanged: still just#"do the work, let somebody else worry about what hosts to run on".

@taskdefdo_work():

run("something interesting on a host")

@taskdefset_hosts(lookup_param):#Update env.hosts instead of calling execute()

env.hosts =external_datastore.query(lookup_param)#调用

fab set_hosts:app do_work

#相比上一种方法,该方法可以轻易替换其他任务,如

fab set_hosts:db snapshot

fab set_hosts:cassandra,cluster2 repair_ring

fab set_hosts:redis,environ=prod status

故障处理:

故障处理也是一个比较实用的东西,fabric默认是"快速失败"的,一旦出现错误,就立即停止。

我们可以通过settings上下文中的env.warn_only=True来临时指定,失败也继续执行。

连接:

fab本身是不对任何主机做远程连接的,她只会设置env.host_string的值(即当前的host)。

NOTE: 连接对象Connection会保存在fabric.state.connections中,并做缓存,以减少创建新连接的消耗。

懒连接:

fab在执行远程操作前,并不会事先去连接远程主机,如:

from fabric.api import *@hosts('host1')defclean_and_upload():

local('find assets/ -name "*.DS_Store" -exec rm'{}'\;')

local('tar czf /tmp/assets.tgz assets/')

put('/tmp/assets.tgz', '/tmp/assets.tgz') //这里才会开始进行远程连接相关的操作:cache.get() ==null?new : cache.get()

with cd('/var/www/myapp/'):

run('tar xzf /tmp/assets.tgz')

关闭连接:

连接缓存并不会关闭连接。fab工具会帮你管理连接,它会遍历所有连接,并在其退出前关闭连接。你也可以调用fabric.network.disconnect_all()来确保关闭所有连接。

多次连接尝试和跳过错误的主机:

fabric在连接远程主机出错之前,会尝试多次(env.connection_attempts,默认为1)连接,每次连接超时env.timeout 秒(默认为10)。

密码管理:

Fabric在内存中维护了两层的密码缓存管理,会记住你登录的密码和sudo时的密码,以免以后再次输入。

第一层密码由 env.password保存,其值为ssh默认密码或sudo提示输入密码。第二层密码保存在env.passwords中,主要用于缓存user/host/port:password。

Fabric还是建议使用密钥进行ssh访问,如无密登录。

使用本地的SSH配置文件:

你可以为Fabric指定特定的ssh配置文件(--ssh-config-path/env.ssh_config_path.),但默认Fabric并没有开启加载配置文件,需要设置env.use_ssh_config为True。

若开启了Fabric加载配置文件的选项,则Fabric为使用以下一些配置项:

User/Port ,HostName, IdentityFile, ForwardAgent, ProxyCommand。

具体参考可见:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值