Ansible 中任务执行控制

Posted 123坤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ansible 中任务执行控制相关的知识,希望对你有一定的参考价值。

1. 循环

循环迭代任务

  1. 简单循环
loop:		##赋值列表
  - value1
  - value2
  - ...

{{item}}	##迭代变量名称

测试
用迭代循环的方式来建立多个用户,编写剧本内容如下所示:

  1 ---
  2 - name: test
  3   hosts: 172.25.254.100
  4   tasks:
  5     - name: create user
  6       user:
  7         name: "{{item}}"
  8         state: present
  9       loop:
 10         - user1
 11         - user2
 12         - user3

执行过程以及结果如下图所示:

在这里插入图片描述
在这里插入图片描述

  1. 循环散列或字典列表

写成字典形式建立用户的剧本如下所示:

  1 ---
  2 - name: test
  3   hosts: 172.25.254.100
  4   tasks:
  5     - name: create user
  6       user:
  7         name: "{{item['name']}}"
  8         uid: "{{item['uid']}}"
  9         state: present
 10       loop:
 11         - name: lll
 12           uid: 11211
 13         - name: xxx
 14           uid: 22111
 15         - name: ggg
 16           uid: 33456

执行效果如下图所示:

在这里插入图片描述

在这里插入图片描述

编写开启服务的剧本如下所示:

---
- name: test
  hosts: 172.25.254.100
  tasks:
    - name: open/off service
      service:
        name: "{{ item.name}}"
        state: "{{ item.state }}"
      loop:
        - name: httpd
          state: started
        - name: vsftpd
          state: stopped

task:
安装 ftp ,允许匿名用户登陆;创建虚拟用户有 user1 的目录在 /var/virtual/user1,密码为 123; 用户 user2 的目录在 /var/virtual/user2,密码为 456。

编写剧本的如下:

 1 ---
  2 - name: VSFTPD
  3   hosts: 172.25.254.100
  4   vars:								##设定变量
  5     Virtual_Users:
  6       - name: user1
  7         home: /var/virtual/user1
  8         password: 123
  9       - name: user2
 10         home: /var/virtual/user2
 11         password: 456
 12   tasks:							##安装服务
 13     - name: install vsftpd
 14       dnf:
 15         name: vsftpd
 16         state: latest
 17 
 18     - name: clear userlistfile		##清理文件内容
 19       file:
 20         path: "{{item}}"
 21         state: absent
 22       loop:
 23         - /etc/vsftpd/vusers
 24         - /etc/pam.d/vusers
 25 
 26     - name: create userlistfile		##创建认证文件
 27       lineinfile:
 28         path: /etc/vsftpd/vusers
 29         line: "{{item.name}}\\n{{item.password}}"
 30         create: yes
 31       loop:
 32         "{{Virtual_Users}}"
 33 
 34     - name: encrpyt userlistfile	##认证文件加密
 35       shell: db_load -T -t hash -f /etc/vsftpd/vusers /etc/vsftpd/vusers.db
 36 
 37     - name: create vuser home		##创建虚拟用户的目录
 38       file:
 39         path: "{{item.home}}"
 40         state: directory
 41       loop:
 42         "{{Virtual_Users}}"
 43 
 44     - name: configure vsftpd		##设定服务的读取规则
 45       lineinfile:
 46         path: /etc/vsftpd/vsftpd.conf
 47         regexp: "{{item.conf_src}}"
 48         line: "{{item.conf_dest}}"
 49 
 50       loop:
 51         - conf_src: anonymous_enable=NO
 52           conf_dest: anonymous_enable=YES
 53         - conf_src: pam_service_name=vsftpd
 54           conf_dest: "pam_service_name=vuser\\nguest_enable=Yes\\nguest_username=ftp\\nlocal_root=/var/    virtual/$USER\\nuser_sub_token=$USER"
 55 
 56     - name: create pam rule file	##建立认证策略
 57       lineinfile:
 58         path: /etc/pam.d/vuser
 59         line: "{{item}}"
 60         create: yes
 61       loop:
 62         - account   required    pam_userdb.so   db=/etc/vsftpd/vusers
 63         - auth      required    pam_userdb.so   db=/etc/vsftpd/vusers
 64 
 65     - name: start vsftpd			##开启服务
 66       service:
 67         name: vsftpd
 68         state: started
 69 
 70     - name: firewalld		##设定火墙
 71       firewalld:
 72         service: ftp
 73         zone: public
 74         permanent: yes
 75         state: enabled
 76         immediate: yes

执行效果如图所示:

在这里插入图片描述

2. 条件

  1. when:
  • 条件1
  • 条件2

条件判断

符号含义
=value == “字符串”,value == 数字,数字不加引号,加上引号之后数字也变为字符串
<value < 数字
>value > 数字
<=value <= 数字
>=value >= 数字
!=value != 数字
is defined value ,value is defined变量存在
is not defined ,value is not defined变量不存在
in , value is in value变量为
not in , value is not in value变量不为
bool变量 为true ,valuevalue的值为true
bool变量 false ,not valuevalue的值为false
value in value2value的值在value2列表中

多条条件组合

when:
  条件1 and 条件2
  - 条件1
  - 条件2

when:
  条件1 or 条件2

when: >
  条件1
  or
  条件2

如编写一个剧本用来判断某个ip 的主机是否网路通畅,当通畅时提示主机开启;内容如下所示:

  1 ---
  2 - name: check
  3   hosts: 172.25.254.100
  4   tasks:
  5     - name: ping
  6       shell:
  7         ping -c1 -w1 172.25.254.200
  8       ignore_errors:  yes	##忽略错误,不然当 ping 不同时就不会执行下面的动作
  9       register: westos		##注册变量
 10     - debug:				##当可以 ping 通时
 11         msg: host is up
 12       when: westos.rc == 0	##对于判定变量的书写不用加括号
 13     - debug:				##当 ping 不通时
 14         msg: host is down
 15       when: westos.rc != 0

执行效果如图所示:

在这里插入图片描述
编写一个剧本来判定受控主机中的设备是否存在,编写剧本如下所示:

  1 ---
  2 - name: check
  3   hosts: 172.25.254.100
  4   tasks:
  5     - debug:
  6         msg: vda is exist
  7       when: ansible_facts['devices']['vda'] is defined
  8     - debug:
  9         msg: vda is not exist
 10       when: ansible_facts['devices']['vda'] is not defined

测试结果如下图所示:

在这里插入图片描述
编辑剧本如下所示:

  1 ---
  2 - name: check
  3   hosts: westos
  4   tasks:
  5     - debug:
  6         msg: vda is exist
  7       when:
  8         - ansible_facts['devices']['vda'] is defined
  9         - inventory_hostname is in "172.25.254.100"
 10     - debug:
 11         msg: vda is not exist
 12       when:
 13         - ansible_facts['devices']['vda'] is not defined
 14         - inventory_hostname is in "172.25.254.100"		##当 hostname 为100 时执行

结果如下图所示:

在这里插入图片描述

test 建立 playbook ~/ansibles/lvm.yml要求如下:

1)建立大小为1500M名为exam_lvm的 lvm 在 westos 组中;
2)如果 westos 不存在请输出: vg westos is not exist;
3)如果 westos 大小不足1500M请输出: vg westos is less then 1500M;
4) 并建立800M大小的 lvm。

编写剧本内容如下所示:

  1 ---
  2 - name: create lvm
  3   hosts: westos
  4   tasks:
  5     - name: check vg		##判定是否被设定
  6       debug:
  7         msg: vg westos is not exist
  8       when: ansible_facts['lvm']['vgs']['westos'] is not defined
  9 
 10     - name: create lv		##创建1500M lv
 11       lvol:
 12         vg: westos
 13         lv: exam_lvm
 14         size: 1500m
 15       when: ansible_facts['lvm']['vgs']['westos'] is defined
 16       ignore_errors: yes		##当创建失败时,忽略错误,继续执行
 17       register: LAG_LVM
 18  
 19     - debug:					##提示小于1500M
 20         msg: vg westos is less then 1500M
 21       when: ansible_facts['lvm']['vgs']['westos'] is defined
 22 
 23     - name: create 800 lv		##创建800M lv
 24       lvol:
 25         vg: westos
 26         lv: exam_lvm
 27         size: 800m
 28       when:
 29         - ansible_facts['lvm']['vgs']['westos'] is defined
 30         - LAG_LVM.rc != 0

3. 触发器

notify: 触发器当遇到更改时触发handlers

handlers: 触发器触发后执行的动作

如当一个服务的配置文件被更改时,会触发重启服务的动作;
编辑一个 playbook 来观察其效果,如下所示:

  1 ---
  2 - name: test
  3   hosts: westos
  4   vars:				##变量值
  5     PORT: 80
  6   tasks:
  7     - name: install apache		##安装服务
  8       dnf:
  9         name: httpd
 10         state: latest
 11     - name: config apache		##编辑配置文件
 12       lineinfile:
 13         path: /etc/httpd/conf/httpd.conf
 14         regexp: "^Listen"
 15         line: Listen "{{PORT}}"
 16       notify: restart apache		##当内容更改之后,将信息传递到 restart apache 所在位置,引起触发器触发接下来的动作。
 17         
 18     - name: start apache
 19       service:
 20         name: httpd
 21         state: started
 22         
 23   handlers:		##当接收的触发信息是,执行接下来的动作。
 24     - name: restart apache
 25       service:
 26         name: httpd
 27         state: restarted

此时 80 是 httpd 的默认端口便不会触发触发器执行重启服务的动作;当更该之后此时执行效果下图所示:

在这里插入图片描述

4. 处理失败任务

  1. ignore_errors
    作用:
    当 play 遇到任务失败是会终止;ignore_errors: yes 将会忽略任务失败使下面的任务继续运行;

如有一个执行错误的playbook 如下所示:

  1 ---
  2 - name: test
  3   hosts: 172.25.254.100
  4   tasks:
  5     - name: install apache
  6       dnf:
  7         name: zxk
  8         state: present
  9 
 10     - name: touch file
 11       file: 
 12         path: /mnt/zxkfile
 13         state: touch

执行效果如下所示:

在这里插入图片描述

当加入参数 ignore_errors: yes 之后,便可继续执行后面的动作:

在这里插入图片描述

  1. force_handlers
    作用:当任务失败后 play 被终止也会调用触发器进程;

在含有触发器的 play 中,当有错误时会导致触发器也不能生效;如图所示:

在这里插入图片描述

当加入参数 force_handlers: yes 之后,此时虽然 play 出错,但是触发器还是会生效;

在这里插入图片描述

  1. changed_when
    作用:控制任务在何时报告它已进行更改;

如更改 apache 端口,当不更改端口时,此时是不会触发触发器,加入此参数的目的是为了不管值会不会更改,都报告已经更改或者没有更改;

  1 ---
  2 - name: test
  3   hosts: 172.25.254.100
  4   vars:
  5     PORT: 80
  6   tasks:
  7     - name: install apache
  8       dnf:
  9         name: httpd
 10         state: latest
 11     - name: config apache
 12       lineinfile:
 13         path: /etc/httpd/conf/httpd.conf
 14         regexp: "^Listen"
 15         line: Listen "{{PORT}}"
 16       notify: restart apache
 17       changed_when: yes
 18 
 19     - name: start apache
 20       service:
 21         name: httpd
 22         state: started
 23 
 24     - name: error
 25       dnf:
 26         name: zxk
 27         state: present
 28       ignore_errors: yes
 29 
 30   handlers:
 31     - name: restart apache
 32       service:
 33         name: httpd
 34         state: restarted

执行效果如下图所示,虽然没有更改端口信息,但是报告出去的是已经更改了内容,此时会重启服务;

在这里插入图片描述

  1. failed_when
    当符合条件时强制任务失败

编写一个 play 来观察实验效果,内容如下所示:

  1 ---
  2 - name: test
  3   hosts: 172.25.254.100
  4   tasks:
  5     - name: shell
  6       shell:
  7         echo hello zxk
  8       register: KKK
  9       ignore_errors: yes
 10       
 11     - name: touch file
 12       file: 
 13         path: /mnt/zxkfile
 14         state: touch

执行结果如下所示:

在这里插入图片描述

此时没有参数,执行时可以输出,当加入参数 failed_when :yes 表示符合条件时强制任务失败 ;

在这里插入图片描述

  1. block
    block: 定义要运行的任务;
    rescue: 定义当block句子中出现失败任务后运行的任务;
    always: 定义最终独立运行的任务;

如编辑一个 playbook 来观察实验效果,用来创建逻辑卷内容如下所示:

  1 ---
  2 - name: test
  3   hosts: westos
  4   tasks:
  5     - name: create lvm
  6       block:		##定义要运行的任务;
  7       - name: create 1500M lv
  8         lvol:
  9           vg: westos
 10           lv: exam_lvm
 11           size: 1500m
 12         when: ansible_facts['lvm']['vgs']['westos'] is defined
 13 
 14       rescue:		##当block中出现失败任务后运行的任务;
 15       - name: create 800M lv
 16         lvol:
 17           vg: westos
 18           lv: exam_lvm
 19           size: 800m
 20         when: ansible_facts['lvm']['vgs']['westos'] is defined
 21 
 22       always:		##定义最终独立运行的任务;
 23       - debug:
 24           msg: vg westos is not exist
 25         when: ansible_facts['lvm']['vgs']['westos'] is not defined

测试练习 建立 playbook ~/westos.yml要求如下:
1)建立大小为 25G 名为 /dev/vdb1 的设备;
2)如果 /dev/vdb 不存在请输入: /dev/vdb is not exis;
3)如果/dev/vdb大小不足 25G 请输出: /dev/vdb is less then 25G;
4)并建立 10G 大小的 /dev/vdb1;此设备挂载到/westos上。

注:可以用命令 ansible-doc parted | less 来查看创建分区时的帮助信息,用命令 ansible-doc filesystem | less 来查看格式化时的帮助信息;用命令 ansible-doc mount | less 来查看挂载时的帮助信息;

编写剧本内容如下所示:

  1 ---
  2 - name: test
  3   hosts: 172.25.254.100
  4   tasks:
  5     - name: create device
  6       block:
  7       - name: create 25G device
  8         parted:
  9           device: /dev/vdb
 10           number: 1
 11           state: present
 12           part_end: 25GiB
 13 
 14       rescue:
 15       - name: create 10G device
 16         block:
 17         - parted:
 18             device: /dev/vdb
 19             number: 1
 20             state: present
 21             part_end: 10GiB
 22     
 23         - debug:  
 24             msg:  /dev/vdb is less then 25G
 25         
 26         rescue:
 27           - debug: 
 28               msg: /dev/vdb is not exist
 29 
 30       always:
 31         - name: create filesystem
 32           filesystem:
 33             fstype: xfs
 34             dev: /dev/vdb1
 35           when: ansible_facts['devices']['vdb'] is defined
 36 
 37         - name:  mount device
 38           mount:
 39             path: /westos
 40             src: /dev/vdb1
 41             fstype: xfs
 42             opts: defaults
 43             state: mounted
 44           when: ansible_facts['devices']['vdb'] is defined

测试结果如下所示:

在这里插入图片描述

在这里插入图片描述

以上是关于Ansible 中任务执行控制的主要内容,如果未能解决你的问题,请参考以下文章

ansible自动化运维详解ansible中的任务执行控制及实例演示:循环条件判断触发器处理失败任务

ansible自动化运维详解ansible中的任务执行控制及实例演示:循环条件判断触发器处理失败任务

ansible自动化运维详解ansible中的任务执行控制及实例演示:循环条件判断触发器处理失败任务

六ansible-playbook任务控制

如何控制Ansible Playbook的执行顺序运行选定的剧本资源

如何控制Ansible Playbook的执行顺序运行选定的剧本资源