ansible register以及循环,判断

register

注意:

register变量的命名不能用 -中横线,比如dev-sda6_result,则会被解析成sda6_result,dev会被丢掉,所以不要用-
ignore_errors这个关键字很重要,一定要配合设置成True,否则如果命令执行不成功,即 echo $?不为0,则在其语句后面的ansible语句不会被执行,导致程序中止。

拉取远程主机 /tmp/test/目录下所有文件

- hosts: ansible-demo3 
  tasks:
    - name: find
      find: paths=/tmp/test/ patterns="*" recurse=yes
      register: file_list

    - name: get
      fetch:src="{{ item.path }}" dest=./
      with_items: "{{ file_list.files }}"

循环

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

with_items迭代列表

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

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

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

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

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 }}"

with_fileglob迭代文件

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

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

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

with_lines迭代行

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

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

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

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个结果。

条件判断

在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