【ansible】实施任务控制

目录

实施任务控制

一,循环(迭代)--- loop

1,利用loop----item循环迭代任务 

2,item---loop循环案例

1,定义item循环列表

2,通过变量应用列表格式

3,字典列表(迭代嵌套子变量)

4,register变量与loop                   

二,when条件任务语法

1, when条件测试案例

2,when条件表达语法

3, 多条件表达and or语法

4,组合循环和有条件判断任务

三,实施处理程序

1,Handlers和notify触发条件

2, tags标签定义

四,处理任务失败

1,ignore_errors 忽略错误继续任务

2, force_handlers: yes

3, failed_when

4, change_when 满足条件输出change状态

5,block、rescue、always块和错误处理


实施任务控制

一,循环(迭代)--- loop

1,利用loop----item循环迭代任务

通过循环管理员不需要编写多个使用同一模块的任务。例:他们不需要编写五个任务来确保存在五个用户,而是只需要编写一个任务来对含有五个用户的列表迭代,从而确保他们都在。

ansible支持loop关键字对一组项目迭代任务,可以配置循环以利用各个项目、列表中各个文件的内容、生成数字序列化或更为复杂的结构来重复任务。

 

 

2,item---loop循环案例

loop关键字添加到任务中,将应对其迭代任务的项目列表取为值。 循环item保存每个迭代过程中使用的值。

确定多个服务运行

1定义item循环列表

(1)查看node1主机上的httpd与named服务是否启动,发现没启动

[root@node1 ~]# systemctl status httpd

[root@node1 ~]# systemctl status named

(2)查看node2主机上的httpd与named服务是否启动,发现没启动

[root@node2 ~]# systemctl status httpd

[root@node2 ~]# systemctl status named

(3)编辑playbook4.yml文件

---

- name: play1

  hosts: test

  tasks:

    - name: task1

      service:

        name: "{{ item }}"

        state: started

      loop:

        - httpd                 //定义item循环列表

        - named                 bind的服务名位named

(4)执行脚本文件playbook4.yml,使其启动httpd服务与bind服务

[root@server var_test]# ansible-playbook playbook4.yml

(5)查看node1主机上的httpd与named服务是否启动,发现此时已经启动

[root@node1 ~]# systemctl status httpd

[root@node1 ~]# systemctl status named

(6)查看node2主机上的httpd与named服务是否启动,发现此时已经启动

[root@node2 ~]# systemctl status httpd

[root@node2 ~]# systemctl status named

2,通过变量应用列表格式

(1)此时node1上的httpd与named服务是关闭的

[root@node1 ~]# systemctl status httpd

[root@node1 ~]# systemctl status named

(2)此时node2上的httpd与named服务是关闭的

[root@node2 ~]# systemctl status httpd

[root@node2 ~]# systemctl status named

(3)编辑playbook4.yml文件

---

- name: play1

  hosts: test

  vars:

    pkname:

      - httpd

      - named

  tasks:

    - name: task1

      service:

        name: "{{ item }}"

        state: started

      loop: "{{ pkname }}"           //通过变量应用列表格式

(4)执行playbook4.yml剧本文件

[root@server var_test]# ansible-playbook playbook4.yml

(5)查看node1主机上的httpd与named服务是否启动,发现此时已经启动

[root@node1 ~]# systemctl status httpd

[root@node1 ~]# systemctl status named

(6)查看node2主机上的httpd与named服务是否启动,发现此时已经启动

[root@node2 ~]# systemctl status httpd

[root@node2 ~]# systemctl status named

3,字典列表(迭代嵌套子变量)

(1)编辑剧本playbook4.yml

---

- name: play1

  hosts: test

  tasks:

    - name: task1

      user:

        name: "{{ item.name }}"

        state: present

        groups: "{{ item.groups }}"

      loop:

        - { name: 'jane',groups: 'wheel'}

        - { name: 'joe', groups: 'root' }

(2)执行剧本playbook4.yml

[root@server var_test]# ansible-playbook playbook4.yml

(3)在node1上可以查看到playbook4中创建的用户以及附加组

[root@node1 ~]# id jane
[root@node1 ~]# id joe

(4)在node2上可以查看到playbook4中创建的用户以及附加组

[root@node2 ~]# id jane
[root@node2 ~]# id joe

4,register变量与loop

(1)编写剧本文件playbook4.yml

- name: play1

  gather_facts: no

  hosts: localhost

  tasks:

    - name: task1

      shell: "echo this is my item: {{ item }}"        

      loop:

        - one

        - two

      register: echo_results               //变量注册

    - name: task2

      debug:

        var: echo_results                    //变量内容显示在屏幕上

(2)执行剧本文件

[root@server var_test]# ansible-playbook playbook4.yml

                    

二,when条件任务语法

when语句用于有条件运行任务。它取要测试的条件为值。如果条件满足,则运行任务。如果条件不满足则跳过任务。

 

 

1, when条件测试案例

案例一:可以测试当run_my_task 为true的时候执行否则不执行

(1)此时的node1主机上没有安装bind

[root@node1 ~]# rpm -q bind  

(2)编辑playbool4.yml文件,使得当my_task为true,在node1安装bind

---

- name: play1

  hosts: node1

  vars:

    my_test: true

  tasks:

    - name: task1

      yum:

        name: bind

      when: my_test

(3)执行剧本playbool4.yml

[root@server var_test]# ansible-playbook playbook4.yml

(4)此时在node1主机上查看bind,发现已经被安装

[root@node1 ~]# rpm -q bind

    案例2: 判断my_service是否有值,若有值则用作安装的软件包名称,若没有定义变量则跳过任务不显示错误

(1)此时的node1主机上没有vsftpd包

[root@node1 ~]# rpm -q vsftpd

(2)编辑playbook4.yml文件,在node1上安装vsftpd包

---

- name: play1

  hosts: node1

  vars:

    my_package: vsftpd

  tasks:

    - name: task1

      yum:

        name: "{{ my_package }}"

      when: my_package is defined

(3)执行剧本playbook4.yml

[root@server var_test]# ansible-playbook playbook4.yml

(4)此时在node1主机上查看vsftpd,发现已经被安装

[root@node1 ~]# rpm -q vsftpd

2,when条件表达语法

操作

示例

等于(值为字符串)

ansible_machine == "x86_64"

等于(值为数字)

max_memory == 512

小于(小于等于)

Min_memory <128 min_memory <= 512

大于 (大于等于)

Min_memory > 256 max_memory >= 512

不等于

Min_memory != 512

变量存在

Min_memory is defined

变量不存在

Min_memory is not defined

布尔值变量是true. 1、True 或yes 的求值为true 变量Memory_available值存在为true则执行

Memory_available

布尔值变量是false. 0、 False 或no的求值为false 变量Memory_available值存在为true则执行

Not memory_available

第一个变量的值存在,在第二个变量的列表中条件满足 (事实变量在变量列表中满足要求)

Ansible_distribution in supported_distros

- name: Demonstrate the inkeyword

  hosts: all

  gather_facts: yes

  Vars:

    supperted_distros:

        - Redhat

        - Fedora

  Tasks:

    - name: Install httpd using yum, where supported

       yum:

           name: http

           state:  present

       when: ansible_distribution in supperted_distros

    When 语句的缩进,由于when语句不是模块变量,他必须通过缩进到任务的最高级别,放置在模块的外面。

    任务是YAML散列/字典,when语句只是任务重的又一个键,就如任务的名称以及它所使用的模块一样。通常的惯例是将可能存在的任何when关键字放在任务名称和模块的后面。

 

 

 

3, 多条件表达and or语法

语法一:

when:ansible_distribution == "Redhat" or ansible_distribution == "Fedora"

When: ansible_distribution_version == "7.5" and ansible_kernel == "3.10.0-327.el7.x86_64"

语法二:

使用and语句时,则必须要所有条件为真时,才执行相应任务

    when:

        - ansible_distribution_version == "7.5"

        - ansible_kernel == "3.10.0-327.el7.x86_64"

    使用括号分组条件,可以更好的表达复制的条件语句

    When: >

         ( ansible_distribution_version == "redhat" and

          ansible_distribution_major_version == "7" )

         or

          (  ansible_distribution_version == "fedora" and

          ansible_distribution_major_version == "28" )

4,组合循环和有条件判断任务

对某类任务结合使用when和loop时,将对每项检查when语句

yum安装软件包,只要/上挂载的文件系统有超过300M的可用空间。 Ansible_mounts 事实是一组字典,各自代表一个已挂在文件系统的相关事实。循环迭代每个字典,只要找到了代表两个条件都为真的已挂载文件系统的字典时,条件语句才得到满足。

- name: install mariadb-server if enough space on root

  yum:

    name: mariadb-server

    state: latest

  loop: "{ ansible_mounts }"                        //字典循环

  when: item.mount == "/" and item.size_available > 300000000            //当两个条件都满足则执行安装

三,实施处理程序

1,Handlers和notify触发条件

  1. notify (通知)此action可用于每个play最后被触发这样避免多次发生改变时都执行指定操作,仅在所有变化发生完成后一次性的执行操作。在notify中列出的操作作为handler及notify中调用handlers中定义的操作。(notify判断是否有发生改变一旦发生改变触发handlers执行指定操作)
  2. handlers (操作者)是task列表这些task和前述的task没有本质区别,用于当关注资源发生变化时才会采取一定的操作。

 

案例:实现只有修改了配置文件才会重启服务

 (1)将/etc/httpd/conf/httpd.conf 复制到/目录下

[root@server var_test]# cp /etc/httpd/conf/httpd.conf /

 

(2)编辑文件/httpd.conf,将端口改为10000

#Listen 80

Listen 10000

 

 

(3)在受控主机node1与node2上关闭防火墙,并设置selinux为permissive

[root@node1 ~]# systemctl stop firewalld
[root@node1 ~]# setenforce 0

 

[root@node2 ~]# systemctl stop firewalld
[root@node2 ~]# setenforce 0

 

(4)创建playbook5.yml文件

- name: handlers test

  hosts: all

  tasks:

    - name: install httpd service

      yum:

        name: httpd

        state: installed

    - name: copy config file

      copy:

        src:  /httpd.conf

        dest: /etc/httpd/conf/httpd.conf

      notify:

         - restart service

    - name: start httpd service

      service:

        name: httpd

        state: started

  handlers: 

    - name: restart service

      service:

        name: httpd

        state: restarted

 

 

 

(5)执行剧本playbook5.yml

因为控制端的端口号为10000,发生了修改,所以会重启服务

[root@server var_test]# ansible-playbook playbook5.yml

 

(6)再次执行剧本文件playbook5.yml,此时的配置文件并未发生任何改变,所以服务并未重新启动

[root@server var_test]# ansible-playbook playbook5.yml

 

(7)此时再将配置文件的端口号由10000改为80

Listen 80

 

 

(8)再次执行剧本playbook5.yml,发现又会重启服务,因为/etc/httpd文件发生改变

[root@server var_test]# ansible-playbook playbook5.yml

 

注意:handlers写在notify模块之后

2, tags标签定义

tags标签: 通过此标签来指定playbook文件执行哪条命令

执行 :-t   标签名

 

案例:仅执行playbook5.yml中的安装httpd命令

 (1)编辑playbook5.yml文件

- name: handlers test

  hosts: all

  tasks:

    - name: install httpd service

      yum:

        name: httpd

        state: installed

      tags: yum_httpd

    - name: copy config file

      copy:

        src:  /httpd.conf

        dest: /etc/httpd/conf/httpd.conf

      notify:

         - restart service

    - name: start httpd service

      service:

        name: httpd

        state: started

  handlers: 

    - name: restart service

      service:

        name: httpd

        state: restarted

 

 

 

 (2)此时执行剧本文件playbook.yml会发现只执行了装包命令

[root@server var_test]# ansible-playbook -t yum_httpd playbook5.yml

 

 

 

四,处理任务失败

1,ignore_errors 忽略错误继续任务

默认情况下任务失败时play会终止。可以通过ingnore乎略失败,其他任务可以继续执行。

案例:

(1)编辑剧本文件playbook6.yml

- name: restart httpd is postfix is running

  hosts: all

  tasks:

    - name: get postfix server status

      command: /usr/bin/systemctl is-active postfix  

    #  ignore_errors: yes         

      register: result       

    - name: restart apache httpd based on postfix status

      service:

        name: httpd

        state: restarted

      when: result.rc == 0

(2)此时受控端主机并未安装postfix,所以任务执行会失败

[root@server var_test]# ansible-playbook playbook6.yml

(3)编辑剧本文件playbook6.yml

- name: restart httpd is postfix is running

  hosts: all

  tasks:

    - name: get postfix server status

      command: /usr/bin/systemctl is-active postfix

      ignore_errors: yes         

      register: result

    - name: restart apache httpd based on postfix status

      service:

        name: httpd

        state: restarted

      when: result.rc == 3

(4)此时受控端主机虽然并未安装postfix,但是会跳过失败,继续执行下面的任务

[root@server var_test]# ansible-playbook playbook6.yml

2, force_handlers: yes

如果任务失败并且play在该主机上终止,则收到play中早前任务通知的处理程序将不会运行。

 

(1)此时的/etc/http配置文件并未做任何改变,所以服务httpd不会自启

[root@server var_test]# ansible-playbook playbook5.yml

 

 

(2)将/etc/httpd配置文件进行修改,notify触发成功,但是后面的服务名错误,force_handlers: yes 关键字还是会执行handlers中的命令

 

Listen 1004

 

 (3)编辑playbook5.yml文件 

- name: handlers test

  force_handlers: yes

  hosts: all

  tasks:

    - name: install httpd service

      yum:

        name: httpd

        state: installed

    - name: copy config file

      copy:

        src:  /httpd.conf

        dest: /etc/httpd/conf/httpd.conf

      notify:

         - restart service

    - name: start httpd service

      service:

        name: http

        state: started

  handlers:  

    - name: restart service 

      service:

        name: httpd

        state: restarted

 

(4)此时执行剧本文件playbook5.yml;即使后面的服务名写错了,也能执行handlers

[root@server var_test]# ansible-playbook playbook5.yml

 

 

 

3, failed_when

failed_when其实是ansible的一种错误处理机制,是由fail模块使用了when条件语句的组合效果。

我们也可以直接通过fail模块和when条件语句,写成如下:

 - name: run user

   shell: /usr/local/bin/create_users.sh

   register: result

   ignore_errors: yes

- name: fail the play if the previous command did not succeed

  fail: 

     msg: "please create user"

  when: "'not' in  result.stdout"

 

4, change_when 满足条件输出change状态

 当我们控制一些远程主机执行某些任务时,当任务在远程主机上成功执行,状态发生更改时,会返回changed状态响应,状态未发生更改时,会返回OK状态响应,当任务被跳过时,会返回skipped状态响应。我们可以通过changed_when来手动更改changed响应状态。

 

(1)Playbook5.yml案例中,如果配置文件/httpd.conf并未发生改变,执行显示ok

[root@server var_test]# ansible-playbook playbook5.yml

 

 (2)编辑playbook5.yml文件

- name: handlers test

  hosts: all

  tasks:

    - name: install httpd service

      yum:

        name: httpd

        state: installed

    - name: copy config file

      copy:

        src:  /httpd.conf

        dest: /etc/httpd/conf/httpd.conf

      register: cmd_v1

      changed_when: not cmd_v1.changed

      notify:

         - restart service

    - name: start httpd service

      service:

        name: httpd

        state: started

  handlers: 

    - name: restart service

      service:

        name: httpd

        state: restarted

 

 

(3)修改后,此时来执行剧本文件playbook5.yml,已经由ok状态变为changed状态

[root@server var_test]# ansible-playbook playbook5.yml

 

 

5,block、rescue、always块和错误处理

通过块,也可结合rescue和always语句来处理错误,如果块中的任何任务失败,则执行其rescue块中的任务来进行恢复。在block子句中的任务以及rescue子句中的任务(如果出现故障)运行之后,always子句中的任务运行。

总结:

  • block: 定义要运行的主要的任务。
  • rescue: 定义要在block子句中定义的任务失败时运行的任务。
  • always:定义始终都独立运行的任务,不论block和rescue子句中定义的任务是否成功还是失败。

block有错才会执行rescuealways怎么都会执行

案例: 在playbook中实施块即使block子句中定义的任务失败,rescue和always子句中定义的任务也会执行。

创建目录文件和文本文件;注意如果默认路径下存在同名文件需要进一步处理才能创建该文件。

(1)编辑playbook7.yml文件

---

- name:

  hosts: localhost

  tasks:

    - name: block module

      block:

        - name:  create directory

          file:

            name: /aaa

            state: directory  

      rescue:

        - name: backup filenmae

          shell: mv /aaa /aaa.backup

        - name: create directory force

          file:

            name: /aaa

            state: directory

            force: yes

      always:

        - name:  create file

          file:

            name: /newfile

            state: touch

(2)执行剧本playbook7.yml文件

[root@server var_test]# ansible-playbook playbook7.yml

(3)目录/aaa与文件/newfile已经被创建

[root@server var_test]# ls -l /aaa
[root@server var_test]# ls -l /newfile
[root@server var_test]# cd /aaa

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值