Ansible系列(六):循环和条件判断

发布日期:2018-02-24    浏览次数:2070

本文目录:
1. 循环
  1.1 with_items迭代列表
  1.2 with_dict迭代字典项
  1.3 with_fileglob迭代文件
  1.4 with_lines迭代行
  1.5 with_nested嵌套迭代
2. 条件判断

1. 循环

ansible中的循环都是借助迭代来实现的。基本都是以"with_"开头。以下是常见的几种循环。

1.1 with_items迭代列表

ansibel支持迭代功能。例如,有一大堆要输出的命令、一大堆要安装的软件包、一大堆要copy的文件等等。

例如,要安装一堆软件包。

---
    - hosts: localhost
      tasks: 
        - yum: name="{{item}}" state=installed
          with_items: 
            - pkg1
            - pkg2
            - pkg3 

它会一个一个迭代到特殊变量"{{item}}"处。

再例如,指定一堆文件列表,然后使用grep搜索出给定文件列表中包含"www.example.com"字符串的文件:

---
    - hosts: localhost
      tasks: 
        - shell: grep -Rl "www\.example\.com" "{{item}}" with_items: 
            - file1
            - file2
            - file3
          register: match_file
        - debug: msg="{% for i in match_file.results %} {{i.stdout}} {% endfor %}" 

注意,将with_items迭代后的结果注册为变量时,其注册结果也是列表式的,且其key为"results"。具体的结果比较长,可以使用debug模块的var或msg参数观察match_file变量的结果。

在上面,是使用for循环进行引用的。如果不使用for循环,那么就需要使用数组格式。例如,引用match_file中的第一和第二个结果。

 - debug: var=match_file.results[0].stdout
 - debug: var=match_file.results[1].stdout 

显然,不如循环引用更好,因为不知道match_file中到底有几个匹配文件,也就不能确定match_file中的列表数量。

每个列表项中可能都包含一个或多个字典,既然with_items迭代的是列表项,那么肯定也能迭代列表中的各字典。

例如:

tasks:
    - command: echo {{ item }}
      with_items: [ 0, 2, 4, 6, 8, 10 ]
      register: num
    - debug: msg="{% for i in num.results %} {{i.stdout}} {% endfor %}" 

再例如:

---
    - hosts: localhost
      tasks: 
        - shell: echo "name={{item.name}},age={{item.age}}" with_items: 
            - {name: zhangsan,age: 32}
            - {name: lisi,age: 33}
            - {name: wangwu,age: 35}
          register: who
        - debug: msg="{% for i in who.results %} {{i.stdout}} {% endfor %}" 

1.2 with_dict迭代字典项

使用"with_dict"可以迭代字典项。迭代时,使用"item.key"表示字典的key,"item.value"表示字典的值。

例如:

--- - hosts: localhost
      tasks:
        - debug: msg="{{item.key}} & {{item.value}}" with_dict: { address: 1,netmask: 2,gateway: 3 } 

另一种情况,字典是已存储好的。例如ansible facts中的ansible_eth0.ipv4,其内容如下:

"ipv4": { "address": "192.168.100.65", "netmask": "255.255.255.0", "gateway": "192.168.100.2" } 

这种情况下,with_dict处可以直接指定该字典的key。即:

--- - hosts: localhost
      tasks:
        - debug: msg="{{item.key}} & {{item.value}}" with_dict: ansible_eth0.ipv4 

再例如,直接引用playbook中定义的vars。

---
 - hosts: 192.168.100.65
   gather_facts: False vars:
     user: 
        longshuai_key: 
           name: longshuai
           gender: Male
        xiaofang_key: 
           name: xiaofang
           gender: Female
   tasks:
      - name: print hash loop var debug: msg="{{ item.key }} & {{ item.value.name }} & {{ item.value.gender }}" with_dict: "{{ user }}" 

1.3 with_fileglob迭代文件

例如,拷贝一堆用通配符匹配出来的文件到各远程主机上。

---
    - hosts: centos
      tasks: 
        - copy: src="{{item}}" dest=/tmp/ with_fileglob:
            - /tmp/*.sh
            - /tmp/*.py 

注意,通配符无法匹配"/",因此无法递归到子目录中,也就无法迭代子目录中的文件。

1.4 with_lines迭代行

with_lines很好用,可以将命令行的输出结果按行迭代。

例如,find一堆文件出来,copy走。

---
    - hosts: localhost
      tasks:
        - copy: src="{{item}}" dest=/tmp/yaml
          with_lines:
            - find /tmp -type f -name "*.yml" 

1.5 with_nested嵌套迭代

嵌套迭代是指多次迭代列表项。例如:

--- - hosts: localhost
      tasks:
        - debug: msg="{{item[0]}} & {{item[1]}}" with_nested: 
            - [a,b]
            - [1,2,3] 

结果将得到"a & 1"、"a & 2"、"a & 3"、"b & 1"、"b & 2"和"b & 3"共6个结果。

2. 条件判断

在ansible中,只有when可以实现条件判断。

tasks: 
  - name: config the yum repo for centos 6 yum_repository:
       name: epel
       description: epel
       baseurl: http://mirrors.aliyun.com/epel/6/$basearch/
       gpgcheck: no when: ansible_distribution_major_version == "6" 

注意两点:

  • when判断的对象是task,所以和task在同一列表层次。它的判断结果决定它所在task是否执行,而不是它下面的task是否执行。
  • when中引用变量的时候不需要加{{ }}符号。

此外,还支持各种逻辑组合。

tasks: # 逻辑或 - command: /sbin/shutdown -h now when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or (ansible_distribution == "Debian" and ansible_distribution_major_version == "7") # 逻辑与 - command: /sbin/shutdown -t now when:
      - ansible_distribution == "CentOS" - ansible_distribution_major_version == "6" # 取反 - command: /sbin/shutdown -t now when: not ansible_distribution == "CentOS" 

还可以直接直接引用布尔值的变量。

---
    - hosts: localhost
      vars:
        epic: False

      tasks:
        - debug: msg="This certainly is epic!" when: not epic 

此外,可以使用jinja2的defined来测试变量是否已定义,使用undefined可以取反表示未定义。例如:

tasks:
    - shell: echo "I've got '{{ foo }}' and am not afraid to use it!" when: foo is defined

    - fail: msg="Bailing out. this play requires 'bar'" when: bar is undefined 

回到Linux系列文章大纲:http://www.wyxxw.cn/blog-detail-22-25-555
回到网站架构系列文章大纲:http://www.wyxxw.cn/blog-detail-22-25-671
回到数据库系列文章大纲:http://www.wyxxw.cn/blog-detail-22-25-670

本文网址:https://www.wyxxw.cn/blog-detail-22-25-630.html

返回列表

非特殊说明,本文版权归原作者所有,转载请注明出处

提示:本站所有资源仅供学习与参考,请勿用于商业用途。图片来自互联网~如侵犯您的权益,请联系QQ:1067507709.

提示:转载请注明来自:http://www.cnblogs.com/f-ck-need-u/p/7575228.html 。 转载人:momo