Linux架构28 ansible流程控制,条件判断when(主机,是否安装,系统版本),循环语句(安装启动,字典定义变量),ansible handlers(触发器)

Ansible 流程控制

一、playbook条件语句

不管是shell还是各大变成语言中,流程控制,条件判断这些都是必不可少的,在我们使用Ansible的过程中,条件判断的使用频率极其高。
例如:
1.我们使用不同的系统的时候,可以通过判断系统来对软件包进行安装。
2.在nfs和rsync安装过程中,客户端服务器不需要推送配置文件,之前我们都是写多个play,会影响效率。
3.我们在源码安装nginx的时候,执行第二遍就无法执行了,此时我们就可以进行判断是否安装过。

1.稍微修改lnmp.yml

#修改部分,使用自己配置好的博客站点目录
- name: Install Wordpress Code
  unarchive:
    src: /root/blog.tar.gz
    dest: /

#添加数据库导入部分
- name: Post wordpress.sql
  copy:
    src: /root/db01/root/wordpress.sql
    dest: /tmp/
    
- name: Import wordpress.sql
  mysql_db:
    state: import
    name: wordpress
    target: /tmp/wordpress.sql

2.判断主机

- name: Create www Group    #如果主机名等于web01,执行下方命令
  group:
    name: www
    gid: 666
    state: present
  when: ansible_fqdn == "web01"    #判断语句中变量不需要加大括号和引号,因为不需要打印
  #when: ansible_fqdn is match "web*"    #当主机名匹配web*,用于多台web
  #when: ansible_fqdn != "db01"    #当主机名不等于db01
  
- name: Create www User    #如果主机名等于web01或web02执行下方命令
  user:
    name: www
    gid: 666
    group: www
    create_home: false
    shell: /sbin/nologin
    state: present
  when: (ansible_fqdn == "web01") or (ansible_fqdn == "web02")    # ()加or表示多个

3.如何判断服务是否安装

通过rpm -qa|grep php 命令返回的$?来判断是否已经安装,0表示安装,1表示未安装

- hosts: web01
  tasks:
    #执行shell,判断服务是否安装,并把结果注册一个变量
    - name: Get PHP Install Status
      shell: "rpm -qa | grep php"
      ignore_errors: yes    #获取状态,加上忽略错误(否则非0报错,不往下执行)
      register: get_php_install_status

    #调用变量,查看内容,如果知道使用什么值判断可以不写
    - name: Get get_php_install_status
      debug:    #输出
        msg: "{{ get_php_install_status }}"

    #调用变量结果,rc值不等于0时执行安装命令
    - name: Install PHP Server
      shell: "yum localinstall -y /tmp/*.rpm"
      when: get_php_install_status.rc != 0    #rc就是$?返回

4.判断系统

[root@m01 base]# vim xitong.yml
- hosts: web01
  tasks:
    - name: Install CentOS apache
      shell: "yum install -y httpd"
      when: ansible_distribution == "CentOS"
      
    - name: Install Ubuntu apache
      shell: "apt-get apache"
      when: ansible_distribution == "Ubuntu"

5.判断系统版本

[root@m01 base]# vim start.yml
- hosts: web01
  tasks:
    - name: Start CentOS6 apache
      shell: "/etc/init.d/httpd start"
      when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "6")
      
    - name: Install Ubuntu apache
      shell: "apt-get apache"
      when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "7")
      
#指定多个条件,除了用and,还可以使用列表形式
- hosts: web01
  tasks:
    - name: Start CentOS6 apache
      shell: "/etc/init.d/httpd start"
      when:
        - ansible_distribution == "CentOS"
        - ansible_distribution_major_version == "6"
      
    - name: Install Ubuntu apache
      shell: "apt-get apache"
      when:
        - ansible_distribution == "CentOS"
        - ansible_distribution_major_version == "7"

6.可以通过提示决定是否执行

#当企业里有很多版本的系统时,先判断版本是否支持服务再进行操作
tasks:
  - shell: echo "only on Red Hat 6, derivatives, and later"
    when: ansible_facts['os_family'] == "RedHat" and ansible_facts['lsb']['major_release']|int >= 7

 block 分组

#使用 block 可以对 task 任务进行分组,将多个 task 任务放到一个 block 下,可以在写一个 when 判断的情况下调用多个 task 任务

[root@ubuntu ~]# cat block-1.yaml
--- #block-1
- hosts: localhost
  tasks:
    - name: task-1
      debug: msg=task-1
      when: ansible_distribution_file_variety == 'RedHat'
    - name: task-2
      debug: msg=task-2
      when: ansible_distribution_file_variety == 'RedHat'

#使用分组写法,一个block 中可以有多个task
[root@ubuntu ~]# cat block-2.yaml 
--- #block-2
- hosts: localhost
  tasks:
    - block:
      - debug: msg=task-1
      - debug: msg=task-2
      when: ansible_distribution_file_variety == 'RedHat'

二、playbook循环语句

1.定义变量循环安装

- hosts: db01
  tasks:
    - name: Install Mariadb Server
      yum:
        name: "{{ package }}"
        state: present
      vars:
        package:
          - mariadb-server
          - MySQL-python

2.定义变量启动服务

#错误配置方法
    - name: Start PHP and Nginx Server
      systemd:
        name: "{{ server }}"
        state: started
        enabled: yes
      vars:    #同时执行,当成一个字符串
        server:
          - php-fpm
          - nginx
          
#正确做法
    - name: Start PHP and Nginx Server
      systemd:
        name: "{{ item }}"    #固定写法
        state: started
        enabled: yes
      with_items:    #固定写法,设置变量,一个一个执行
        - php-fpm
        - nginx

 

3.字典定义变量

    #创建用户组
    - name: Create www lhd test Group
      group:
        name: "{{ item.name }}"
        gid: "{{ item.gid }}"
        state: present
      with_items:
        - { name: "www", gid: "666"}
        - { name: "lhd", gid: "777"}
        - { name: "test", gid: "888"}
    
    #创建多个用户
    - name: Create www lhd test User
      user:
        name: "{{ item.name }}"
        uid: "{{ item.uid }}"
        group: "{{ item.group }}"
        create_home: "{{ item.create_home }}"
        shell: "{{ item.shell }}"
        state: present
      with_items:
        - { name: "www", uid: "666", group: "www", create_home: "false", shell: "/sbin/nologin"}
        - { name: "lhd", uid: "777", group: "lhd", create_home: "true", shell: "/sbin/nologin"}
        - { name: "test", uid: "888", group: "test", create_home: "false", shell: "/bin/bash"}
        
    #创建多个目录(赋权,没有目录就会创建)
    - name: Chown Code Dir
      file:
        path: "{{ item.path }}"
        state: directory
        owner: "{{ item.user }}"
        group: "{{ item.user }}"
        recurse: yes
      with_items:
        - { path: "/code", user: "www" }
        - { path: "/data", user: "lhd" }

4.利用字典定义方式优化lnmp.yml

    - name: Config Nginx Server
      copy:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      with_items:
        - { src: "/root/nginx.conf", dest: "/etc/nginx/" }
        - { src: "/root/wordpress.conf", dest: "/etc/nginx/conf.d/" }


    - name: Tar PHP and Wordpress Package
      unarchive:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      with_items:
        - { src: "/root/php.tar.gz", dest: "/tmp/" }
        - { src: "/root/blog.tar.gz", dest: "/" }      

 

三、ansible handlers (触发器)

1.handlers、notify作用

Handlers本质上也是task list,也定义了一系列的task,每个task中同样调用指定模块执行操作,只不过Handlers中定义的task,不会主动执行,需要配合notify,
让notify通知相应的Handers中的task,该task才会执行,而且,Handers中的task,是在playbook的tasks中所有的task都执行完成之后才调用,
这样是为了避免多次触发同一个 Hander 导致多次调用。notify配合handlers,可以实现在特定条件下触发某些操作,特别适用于类似于服务重启,重载等场景。 如果文件变化,可以通过Notify 通知给指定的 handlers 触发器,然后执行相应重启服务的操作,如果配置文件不发生变更操作,则不会触发 Handlers 任务的执行;

2.配置触发器

#分发 ngx配置文件ansible...conf
#重启ngx

#使用ngtify与handlers 实现配置变化自动出发重启
- hosts: web01
  gather_facts: false
  tasks:
    - name: fenfa ngx conf
      copy:
        src: ansible.oldboylinux.cn.conf
        dest: /etc/nginx/conf.d/
        backup: yes
      notify:    #监控是否有变化,有变化就触发,调用下方的handlers,可以写多个
        - ngx restart
  handlers:    #如果配置文件发生变化会调用该handlers下面的对应名称的task
    - name: ngx restart
      systemd:
        name: nginx
        state: reloaded

3.触发器注意事项

1、无论多少个 task 通知了相同的 handlers , handlers 仅会在所有tasks 结束后运行一次。
2、只有 task 发生改变了才会通知 handlers ,没有改变则不会触发handlers。
3、handlers 是在所有前面的 tasks 都成功执行才会执行,如果前面任何一个 task 失败,会导致 handler 跳过执行
4、不能使用 handlers 替代 tasks 、因为 handlers 是一个特殊的 tasks。 5、notify后的名称需与handlers中定义的name一致 6、handlers与tasks同级

 注意: ansible-playbook的特点是如果当中有一个task执行失败,那么下面的task都不会执行

 

force_handlers 强制执行 handlers

在 task 中使用 notify 来调用 handlers 中的任务,如果该 task 执行失败,或者在该 task 之前的其它task 执行失败,
则会导致 notify 通知的 handlers 中的任务不会被调用,想要保证 handlers 中的 task 一定会被调用,则可以用 force_handlers 强制指定。 注意:force_handlers 是以整个 playbook 的角度来理解的,在 playbook 中,如果有 task 执行失败,那整个 playbook 也执行失败,
即使有部份 task 执行成功,这部份 task 对应的 handlers 也不会被执行,force_handlers 保证的是己成功执行的 task 对应的 handlers 一定会被执行。
#task 出错,会导致所有 handler 都不会被执行 [root@ubuntu ~]# cat force_handlers-v2.yaml --- #force_handlers-v2 - hosts: localhost gather_facts: no tasks: - name: task-1 shell: echo "task-1" notify: handlers-1 - name: task-2 shell: echoooooo "task-2" #此行出错,会导致 handlers-1, handlers-2 都 不执行 notify: handlers-2 handlers: - name: handlers-1 debug: msg="handlers-1" - name: handlers-2 debug: msg="handlers-2" #force_handlers 可以保证 handlers-1 被执行 [root@ubuntu ~]# cat force_handlers-v3.yaml --- #force_handlers-v3 - hosts: localhost gather_facts: no force_handlers: yes tasks: - name: task-1 shell: echo "task-1" notify: handlers-1 - name: task-2 shell: echoooooo "task-2" notify: handlers-2 handlers: - name: handlers-1 debug: msg="handlers-1" - name: handlers-2 debug: msg="handlers-2" #force_handlers 可以保证 handlers-1 被执行 #handlers-2,handers-3 都不会执行,因为 task-2 执行失败,task-3 不会被执行 [root@ubuntu ~]# cat force_handlers-v4.yaml --- #force_handlers-v4 - hosts: localhost gather_facts: no force_handlers: yes tasks: - name: task-1 shell: echo "task-1" notify: handlers-1 - name: task-2 shell: echoooooo "task-2" notify: handlers-2 - name: task-3 shell: echo "task-3" notify: handlers-3 handlers: - name: handlers-1 debug: msg="handlers-1" - name: handlers-2 debug: msg="handlers-2" - name: handlers-3 debug: msg="handlers-3"

 

posted @ 2024-04-09 14:45  战斗小人  阅读(201)  评论(0编辑  收藏  举报