博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自动化运维工具Ansible实战(七)playbook循环
阅读量:6845 次
发布时间:2019-06-26

本文共 6178 字,大约阅读时间需要 20 分钟。

(一)简述

    在使用ansible做自动化运维的时候,免不了的要重复执行某些操作,如:添加几个用户,创建几个MySQL用户并为之赋予权限,操作某个目录下所有文件等等。好在playbook支持循环语句,可以使得某些需求很容易而且很规范的实现。

(二)常用的循环语句

1,with_items。with_items是playbooks中最基本也是最常用的循环语句:

语法:

1
2
3
4
5
6
7
8
9
tasks:
- name:Secure config files
    
file
: path=
/etc/
{
{ item }} mode=0600 owner=root group=root
    
with_items:
        
- my.cnf
        
- shadow
        
- fstab
    
或with_items:
"{
{ somelist }}"
###上面的例子说明在/etc下创建权限级别为600,属主属组都是root三个文件
1
2
3
4
5
6
7
使用with_items迭代循环的变量可以是个单纯的列表,也可以是一个较为复杂 的数据结果,如字典类型:
tasks:
- name: add several 
users
  
user: name={
{ item.name }} state=present 
groups
={
{ item.
groups 
}}
  
with_items:
    
- { name: 
'testuser1'
groups
'wheel' 
}
    
- { name: 
'testuser2'
groups
'root' 
}


2、with_nested嵌套循环

示例:

1
2
3
4
5
6
tasks:
- name: give 
users 
access to multiple databases
  
mysql_user: name={
{ item[0] }} priv={
{ item[1] }}.*:ALL append_privs=
yes 
password=foo
  
with_nested:
    
- [ 
'alice'
'bob' 
]
    
- [ 
'clientdb'
'employeedb'
'providerdb' 
]

item[0]是循环的第一个列表的值['alice','bob']。item[1]是第二个列表的值。表示循环创建alice和bob两个用户,并且为其赋予在三个数据库上的所有权限。

也可以将用户列表事先赋值给一个变量:

1
2
3
4
5
6
tasks:
- name: here, 
'users' 
contains the above list of employees
  
mysql_user: name={
{ item[0] }} priv={
{ item[1] }}.*:ALL append_privs=
yes 
password=foo
  
with_nested:
    
"`users`"
    
- [ 
'clientdb'
'employeedb'
'providerdb' 
]

3、with_dict

with_dict可以遍历更复杂的数据结构。假如有如下变量内容:

1
2
3
4
5
6
7
users
:
  
alice:
    
name: Alice Appleworth
    
telephone: 123-456-7890
  
bob:
    
name: Bob Bananarama
    
telephone: 987-654-3210
1
2
3
4
5
####现在需要输出每个用户的用户名和手机号:
tasks:
  
- name: Print phone records
    
debug: msg=
"User {
{ item.key }} is {
{ item.value.name }} ({
{ item.value.telephone }})"
    
with_dict: 
"{
{ users }}"

4、with_fileglob文件匹配遍历

1
2
3
4
5
6
7
8
9
10
####可以指定一个目录,使用with_fileglob可以循环这个目录中的所有文件,示例如下:
tasks:
- name:Make key directory     
      
file
: path=
/root/
.sshkeys ensure=directory mode=0700 owner=root group=root     
- name:Upload public keys     
      
copy: src={
{ item }} dest=
/root/
.sshkeys mode=0600 owner=root group=root     
      
with_fileglob:
        
- keys/*.pub     
- name:Assemble keys into authorized_keys 
file     
      
assemble: src=
/root/
.sshkeys dest=
/root/
.
ssh
/authorized_keysmode
=0600 owner=root group=root

5、with_subelement遍历子元素

假如现在需要遍历一个用户列表,并创建每个用户,而且还需要为每个用户配置以特定的SSH key登录。变量文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
users
:
  
- name: alice
    
authorized:
      
/tmp/alice/onekey
.pub
      
/tmp/alice/twokey
.pub
    
mysql:
        
password: mysql-password
        
hosts:
          
"%"
          
"127.0.0.1"
          
"::1"
          
"localhost"
        
privs:
          
"*.*:SELECT"
          
"DB1.*:ALL"
  
- name: bob
    
authorized:
      
/tmp/bob/id_rsa
.pub
    
mysql:
        
password: other-mysql-password
        
hosts:
          
"db1"
        
privs:
          
"*.*:SELECT"
          
"DB2.*:ALL"
1
2
3
4
5
6
7
###playbook中定义如下:
- user: name={
{ item.name }} state=present generate_ssh_key=
yes
  
with_items: 
"`users`"
- authorized_key: 
"user={
{ item.0.name }} key='{
{ lookup('file', item.1) }}'"
  
with_subelements:
     
users
     
- authorized
1
2
3
4
5
6
###也可以遍历嵌套的子列表:
- name: Setup MySQL 
users
  
mysql_user: name={
{ item.0.name }} password={
{ item.0.mysql.password }} host={
{ item.1 }} priv={
{ item.0.mysql.privs | 
join
(
'/'
) }}
  
with_subelements:
    
users
    
- mysql.hosts

6、with_sequence循环整数序列

with_sequence可以生成一个自增的整数序列,可以指定起始值和结束值,也可以指定增长步长。 参数以key=value的形式指定,format指定输出的格式。数字可以是十进制、十六进制、八进制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- hosts: all
  
tasks:
    
# create groups
    
- group: name=evens state=present
    
- group: name=odds state=present
    
# create some test users
    
- user: name={
{ item }} state=present 
groups
=evens
      
with_sequence: start=0 end=32 
format
=testuser%02d
    
# create a series of directories with even numbers for some reason
    
file
: dest=
/var/stuff/
{
{ item }} state=directory
      
with_sequence: start=4 end=16 stride=2    
# stride用于指定步长
    
# a simpler way to use the sequence plugin
    
# create 4 groups
    
- group: name=group{
{ item }} state=present
      
with_sequence: count=4

7、with_random_choice随机选择

从列表中随机取一个值:

1
2
3
4
5
6
- debug: msg={
{ item }}
  
with_random_choice:
     
"go through the door"
     
"drink from the goblet"
     
"press the red button"
     
"do nothing"

8、do-Util循环

示例:

1
2
3
4
5
- action: shell 
/usr/bin/foo
  
register: result
  
until
: result.stdout.
find
(
"all systems go"
) != -1
  
retries: 5
  
delay: 10

重复执行shell模块,当shell模块执行的命令输出内容包含"all systems go"的时候停止。重试5次,延迟时间10秒。retries默认值为3,delay默认值为5。任务的返回值为最后一次循环的返回结果。

9、循环注册变量

在循环中使用register时,保存的结果中包含results关键字,该关键字保存模块执行结果的列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
- shell: 
echo 
"{
{ item }}"
  
with_items:
    
- one
    
- two
  
register: 
echo
变量
echo
内容如下:
{
    
"changed"
true
,
    
"msg"
"All items completed"
,
    
"results"
: [
        
{
            
"changed"
true
,
            
"cmd"
"echo \"one\" "
,
            
"delta"
"0:00:00.003110"
,
            
"end"
"2013-12-19 12:00:05.187153"
,
            
"invocation"
: {
                
"module_args"
"echo \"one\""
,
                
"module_name"
"shell"
            
},
            
"item"
"one"
,
            
"rc"
: 0,
            
"start"
"2013-12-19 12:00:05.184043"
,
            
"stderr"
""
,
            
"stdout"
"one"
        
},
        
{
            
"changed"
true
,
            
"cmd"
"echo \"two\" "
,
            
"delta"
"0:00:00.002920"
,
            
"end"
"2013-12-19 12:00:05.245502"
,
            
"invocation"
: {
                
"module_args"
"echo \"two\""
,
                
"module_name"
"shell"
            
},
            
"item"
"two"
,
            
"rc"
: 0,
            
"start"
"2013-12-19 12:00:05.242582"
,
            
"stderr"
""
,
            
"stdout"
"two"
        
}
    
]
}
1
2
3
4
5
6
##遍历注册变量的结果:
- name: Fail 
if 
return 
code is not 0
  
fail:
    
msg: 
"The command ({
{ item.cmd }}) did not have a 0 return code"
  
when: item.rc != 0
  
with_items: 
"`echo`.`results`"

10、with_together遍历数据并行集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
示例:
- hosts: webservers
  
remote_user: root
  
vars:
    
alpha: [ 
'a'
,
'b'
,
'c'
,
'd'
]
    
numbers: [ 1,2,3,4 ]
  
tasks:
    
- debug: msg=
"{
{ item.0 }} and {
{ item.1 }}"
      
with_together:
         
"{
{ alpha }}"
         
"{
{ numbers }}"
输出的结果为:
ok: [192.168.1.65] => (item=[
'a'
, 1]) => {
    
"item"
: [
        
"a"
,
        
1
    
],
    
"msg"
"a and 1"
}
ok: [192.168.1.65] => (item=[
'b'
, 2]) => {
    
"item"
: [
        
"b"
,
        
2
    
],
    
"msg"
"b and 2"
}
ok: [192.168.1.65] => (item=[
'c'
, 3]) => {
    
"item"
: [
        
"c"
,
        
3
    
],
    
"msg"
"c and 3"
}
ok: [192.168.1.65] => (item=[
'd'
, 4]) => {
    
"item"
: [
        
"d"
,
        
4
    
],
    
"msg"
"d and 4"
}

 

loop模块一般在下面的场景中使用

  1. 类似的配置模块重复了多遍

  2. fact是一个列表

  3. 创建多个文件,然后使用assemble聚合成一个大文件

  4. 使用with_fileglob匹配特定的文件管理

本文转自 lqbyz 51CTO博客,原文链接:http://blog.51cto.com/liqingbiao/1969595

转载地址:http://phpul.baihongyu.com/

你可能感兴趣的文章
Codeforces Round #109 (Div. 2) A. I_love_%username%【打擂台算法/满足当前数字在已经出现的数字的最大值和最小值之间的个数】...
查看>>
一起谈.NET技术,ASP.NET MVC 2中使用jQuery UI控件详解
查看>>
信息架构,互联网营销
查看>>
java实现简单邮件的发送以及常见问题
查看>>
第四次scrum冲刺
查看>>
linux配置sftp简单过程
查看>>
boost bind 表达式中的是值语义还是指针语义?
查看>>
【哲学】近代认识论学派间的一些分歧
查看>>
理解height 百分比 height:100%
查看>>
JBPM (三) 服务和实例介绍
查看>>
java线程之——sleep()与wait()的区别
查看>>
JavaScript 基础数组循环和迭代的几种方法
查看>>
Nuget发布教程
查看>>
让SQL SERVER自动清理掉处于SLEEPING状态超过30分钟的进程(转)
查看>>
【036】◀▶ 自己写的程序源代码
查看>>
performance_schema 变量
查看>>
Pixhawk 添加超声波定高
查看>>
error while loading shared libraries: xxx.so.x"错误的原因和解决办法
查看>>
在微软平台上运行 SAP 应用程序
查看>>
ubuntu下安装lamp环境
查看>>