ansible playbook中when的多种用法和playbook handler

Posted syy1757528181

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ansible playbook中when的多种用法和playbook handler相关的知识,希望对你有一定的参考价值。

回顾

剧本中可以使用判断的方式,减少hosts(play)的个数

template  jinjia2
剧本中不能使用if判断,使用when判断

shutdown -a 取消关机
shutdown -s 关机
shutdown -f 强行关闭应用程序
shutdown -m \计算机名 控制远程计算机
shutdown -i 显示“远程关机”图形用户界面,但必须是Shutdown的第一个参数  
shutdown -l 注销当前用户
shutdown -r 关机并重启
shutdown -s -t 时间 设置关机倒计时
shutdown -h 休眠

centos6启动httpd		/etc/init.d/httpd start

变量的使用并不能减少代码量,使用循环就可以减少代码量了
还原快照要重新推送m01上的公钥,才能使用ansible
bool值纯数字要加引号,字符串不用加
yum localinstall 在剧本中不会报错

文件类型:str 
		int	字符串类型
python中文件类型的区分是很严格的,
剧本中变量加双引号

循环一般在启动服务或者copy的时候使用
yum支持列表,一般不用循环

命令行不支持字典的形式调用变量,playbook支持

根据不同的操作系统安装apache

官方示例:

- hosts: all
  tasks:
    - name: "shut down Debian flavored systems"
      command: /sbin/shutdown -t now
      when: ansible_facts[‘os_family‘] == "Debian"		#不等于表示:!= 0
      # 注意,‘所有变量‘都可以直接在条件语句中使用,而无需使用双大括号
  - hosts: web_group
    tasks:
      - name: Install CentOS Httpd
        yum:
          name: httpd
          state: present
      #官方
        when: ansible_[‘os_family‘] == "CentOS"		#判断系统
        when: ansible.os_family == "CentOS"
      #非官方()
        when: ansible_distribution == "CentOS"
  
      - name: Install Ubuntu Httpd
        yum:
          name: apache2
          state: present
        when: ansible_facts[‘os_family‘] == "Ubuntu"
        
  when后面既可以是变量,又可以是指定值,一般后面跟变量,与hosts一起使用     
[root@www ~]# ansible web01 -m setup |grep os_family
        "ansible_os_family": "RedHat",
when的缩进和name注释一样  
#facts 指的是 ansible_facts 变量,ansible 中使用 setup 模块来获取,包含系统的大部分基础硬件信息

还可以使用括号,and , or对条件进行分组

tasks:
  - name: "shut down CentOS 6 and Debian 7 systems"
    command: /sbin/shutdown -t now
    when: (ansible_facts[‘distribution‘] == "CentOS" and ansible_facts[‘distribution_major_version‘] == "6") or
          (ansible_facts[‘distribution‘] == "Debian" and ansible_facts[‘distribution_major_version‘] == "7")
          
        #使用ansible_facts[‘distribution‘] 判断系统  注意大小写

也可以指定多条件为列表(and 并且)

tasks:
  - name: "shut down CentOS 6 systems"
    command: /sbin/shutdown -t now
    when:
      - ansible_facts[‘distribution‘] == "CentOS"
      - ansible_facts[‘distribution_major_version‘] == "6"
      
      #列表形式等效于and

条件运算

tasks:
  - shell: echo "only on Red Hat 6, derivatives, and later"
    when: ansible_facts[‘os_family‘] == "RedHat" and ansible_facts[‘lsb‘][‘major_release‘]|int >= 6		#

rsync服务端推送配置文件

[root@m01 ~]# cat rsyncd/rsyncd.yml
- hosts: all						######
  tasks:
    - name: Install Rsyncd Server
      yum:
        name: rsync
        state: present					#可在这里使用ls -l 判断rsync是否安装

    - name: Create www Group
      group:
        name: www

        gid: 666
    - name: Create www User
      user:
        name: www
        group: www
        uid: 666
        create_home: false
        shell: /sbin/nologin

    - name: Scp Rsync Config
      copy:
        src: ./rsyncd.j2
        dest: /etc/rsyncd.conf
        owner: root
        group: root
        mode: 0644
      when: ansible_hostname == "backup" 		#判断主机名

    - name: Create Passwd File
      copy:
        content: ‘rsync_backup:123‘
        dest: /etc/rsync.passwd
        owner: root
        group: root
        mode: 0600
      when: ansible_hostname == "backup"

    - name: Create backup Directory
      file:
        path: /backup
        state: directory
        mode: 0755
        owner: www
        group: www
        recurse: yes
      when: ansible_hostname == "backup"

    - name: Start Rsyncd Server
      systemd:
        name: rsyncd
        state: started
      when: ansible_hostname == "backup"
      

rsync客户端推送脚本

[root@m01 ~]# vim rsync.yml
- hosts: rsync_server
  tasks:
    - name: SCP Backup Shell
      copy:
        src: ./backup.sh
        dest: /root/backup.sh
      when: ansible_hostname is match "web*"		#when支持通配符
      when: ansible_hostname ~= "web*"		
      #when: ansible_hostname == "backup" or ansible_hostname == "nfs"
      #这三种方式类似模糊匹配,都可以匹配多台web
      #模糊匹配和and or不能一起使用

通过register将命令执行结果保存至变量,然后通过when语句进行判断

- hosts: web_group
  tasks:
    - name: Check Httpd Server
      command: systemctl is-active httpd		#查看服务状态
      ignore_errors: yes			#忽略报错,继续执行
      register: check_httpd			#将命令的执行结果注册变量

    - name: debug outprint
      debug: var=check_httpd		#偶尔调试

    - name: Httpd Restart
      service:
        name: httpd
        state: restarted
      when: check_httpd.rc == 0
#通过变量注册的方式可以进行非系统变量的调用,与‘register: check_httpd‘对应

#htpd
[root@lb01 ~]# systemctl is-active httpd
active
[root@lb01 ~]# systemctl stop httpd
[root@lb01 ~]# systemctl is-active httpd
unknown

#nginx
[root@lb01 ~]# systemctl is-active nginx
active
[root@lb01 ~]# systemctl stop nginx
[root@lb01 ~]# systemctl is-active nginx
failed

playbook循环语句

在之前的学习过程中,我们经常会有传送文件,创建目录之类的操作,创建2个目录就要写两个file模块来创建,如果要创建100个目录,我们需要写100个file模块???妈耶~~~~ 当然不是,只要有循环即可,减少重复性代码。


启动多个服务

- hosts: web_group
  tasks:
    - name: start service
      systemd:
        name: "{{ item }}"
        state: started
      with_items:
        - httpd
        - php-fpm
        - mariadb

定义变量循环

- name: ensure a list of packages installed
  yum:
    name: "{{ packages }}"
  vars:									#模块内定义变量
    packages:
    - httpd
    - httpd-tools
- hosts: web_group
  tasks:
    - name: ensure a list of packages installed
      yum: name= "{{ item }}" state=present			#可以使用多个‘=‘
      with_items:
        - httpd
        - httpd-tools
        
#with_items一般放到模块的末尾,与模块同一缩进级别        

字典循环

1.创建用户

[root@m01 ~]# cat loop.yml
- hosts: web_group
  tasks:
    - name: Add Users
      user:
        name: "{{ item.name }}"
        groups: "{{ item.groups }}"
        state: present
      with_items:
        - { name: ‘zls‘, groups: ‘linux‘ }
        - { name: ‘egon‘, groups: ‘python‘ }

2.拷贝文件

- hosts: web_group
  tasks:
    - name: copy conf and code
      copy:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
        mode: "{{ item.mode }}"
      with_items:
        - { src: "./httpd.conf", dest: "/etc/httpd/conf/", mode: "0644" }
        - { src: "./upload_file.php", dest: "/var/www/html/", mode: "0600" }
        
        #同一模块在一个剧本中多次出现,即可考虑使用循环
        #同一模块在一个剧本中多次出现,对同一主机多次操作,即可考虑字典循环

playbook handler

handler用来执行某些条件下的任务,比如当配置文件发生变化的时候,通过notify触发handler去重启服务。

实践案例

[root@m01 ~]# cat handler.yml 
- hosts: web_group
  vars:
    - http_port: 8080
  tasks:
    - name: Install Http Server
      yum:
        name: httpd
        state: present

    - name: config httpd server
      template:
        src: ./httpd.j2
        dest: /etc/httpd/conf
      notify: 							#
        - Restart Httpd Server
        - Restart PHP Server

    - name: start httpd server
      service:
        name:httpd
        state: started
        enabled: yes

  handlers:								#
    - name: Restart Httpd Server			
      systemd:
        name: httpd
        state: restarted 

    - name: Restart PHP Server
      systemd:
        name: php-fpm
        state: restarted

练习:多个nginx配置文件的推送及触发器

注意:
1.无论多少个task通知了相同的handlers,handlers仅会在所有tasks结束后运行一次

2.Handlers只有在其所在的任务被执行时,才会被运行;如果一个任务中定义了notify调用Handlers,但是由于条件判断等原因,该任务未被执行,那么Handlers同样不会被执行。

3.Handlers只会在每一个play的末尾运行一次;如果想在一个playbook中间运行Handlers,则需要使用meta模块来实现。例如: -meta: flush_handlers。

4.如果一个play在运行到调用Handlers的语句之前失败了,那么这个Handlers将不会被执行。我们可以使用meta模块的--force-handlers选项来强制执行Handlers,即使Handlers所在的play中途运行失败也能执行。

5.不能使用handlers替代tasks


playbook任务标签

默认情况下,Ansible在执行一个playbook时,会执行playbook中定义的所有任务,Ansible的标签(tag)功能可以给单独任务甚至整个playbook打上标签,然后利用这些标签来指定要运行playbook中的个别任务,或不执行指定的任务。


打标签的方式

1.对一个task打一个标签
2.对一个task打多个标签
3.对多个task打一个标签


打完标签如何使用

-t:执行指定的tag标签任务
--skip-tags:执行--skip-tags之外的标签任务


使用-t指定tag

[root@m01 m01]# cat tag.yml 
- hosts: web_group
  vars:
    - http_port: 8080
  tasks:
    - name: Install Http Server
      yum:
        name: httpd
        state: present
      tags: 
        - install_httpd
        - httpd_server

    - name: configure httpd server
      template:
        src: ./httpd.j2
        dest: /etc/httpd/conf/httpd.conf
      notify: Restart Httpd Server
      tags: 
        - config_httpd
        - httpd_server

    - name: start httpd server
      service:
        name: httpd
        state: started
        enabled: yes
      tags: service_httpd

  handlers:
    - name: Restart Httpd Server
      systemd:
        name: httpd
        state: restarted 

[root@m01 m01]# ansible-playbook tag.yml --list-tags
[root@m01 m01]# ansible-playbook tag.yml -t httpd_server
[root@m01 m01]# ansible-playbook tag.yml -t install_httpd,confiure_httpd
[root@m01 m01]# ansible-playbook tag.yml --skip-tags httpd_server

playbook文件复用

在之前写playbook的过程中,我们发现,写多个playbook没有办法,一键执行,这样我们还要单个playbook挨个去执行,很鸡肋。所以在playbook中有一个功能,叫做include用来动态调用task任务列表。

技术图片?

只调用task:include_tasks
调用整个task文件:include (新版本:import_playbook)

在saltstack中,叫做top file入口文件。

示例一:

[root@m01 m01]# cat task.yml 
- hosts: web_group
  vars:
    - http_port: 8080

  tasks:
    - include_tasks: task_install.yml
    - include_tasks: task_configure.yml
    - include_tasks: task_start.yml

  handlers:
    - name: Restart Httpd Server
      systemd:
        name: httpd
        state: restarted

[root@m01 m01]# cat task_install.yml 
- name: Install Http Server
  yum:
    name: httpd
    state: present

[root@m01 m01]# cat task_configure.yml 
- name: configure httpd server
  template:
    src: ./httpd.j2
    dest: /etc/httpd/conf/httpd.conf
  notify: Restart Httpd Server

[root@m01 m01]# cat task_start.yml 
- name: start httpd server
  service:
    name: httpd
    state: started
    enabled: yes

示例二

- include: httpd.yml
- include: nfs.yml
- include: rsync.yml

示例三

- import_playbook: httpd.yml
- import_playbook: nfs.yml
- import_playbook: rsync.yml

playbook忽略错误

默认playbook会检测task执行的返回状态,如果遇到错误则会立即终止playbook的后续task执行,然鹅有些时候playbook即使执行错误了也要让其继续执行。

加入参数:ignore_errors:yes 忽略错误

[root@m01 ~]# cat ignore.yml
---
- hosts: web_group
  tasks:
    - name: Ignore False
      command: /bin/false
      ignore_errors: yes
      
    - name: touch new file
      file:
        path: /tmp/zls.txt
        state: touch

playbook错误处理

如上所述,当task执行失败时,playbook将不再继续执行,包括如果在task中设置了handler也不会被执行。

但是我们可以采取强制措施...


强制调用handler

[root@m01 ~]# cat handler.yml 
- hosts: web_group
  vars:
    - http_port: 8080
  force_handlers: yes
  tasks:

    - name: config httpd server
      template:
        src: ./httpd.j2
        dest: /etc/httpd/conf
      notify: 
        - Restart Httpd Server
        - Restart PHP Server

    - name: Install Http Server
      yum:
        name: htttpd
        state: present

    - name: start httpd server
      service:
        name:httpd
        state: started
        enabled: yes

  handlers:
    - name: Restart Httpd Server
      systemd:
        name: httpd
        state: restarted 

    - name: Restart PHP Server
      systemd:
        name: php-fpm
        state: restarted

抑制changed

被管理主机没有发生变化,可以使用参数将change状态改为ok

[root@m01 ~]# cat handler.yml 
- hosts: web_group
  vars:
    - http_port: 8080
  force_handlers: yes
  tasks:
    - name: shell
      shell: netstat -lntup|grep httpd
      register: check_httpd
      changed_when: false

    - name: debug
      debug: msg={{ check_httpd.stdout.lines }}
[root@m01 project2]# cat changed_when.yml 
- hosts: webservers
  vars:
    - http_port: 8080
  tasks:
    - name: configure httpd server
      template:
        src: ./httpd.j2
        dest: /etc/httpd/conf/httpd.conf
      notify: Restart Httpd Server

    - name: Check HTTPD
      shell: /usr/sbin/httpd -t
      register: httpd_check
      changed_when: 
        - httpd_check.stdout.find(‘OK‘)
        - false

    - name: start httpd server
      service:
        name: httpd
        state: started
        enabled: yes

  handlers:
    - name: Restart Httpd Server
      systemd:
        name: httpd
        state: restarted 





以上是关于ansible playbook中when的多种用法和playbook handler的主要内容,如果未能解决你的问题,请参考以下文章

Ansible之Playbooks的when语句

ansible条件判断when

ansible-playbook权限提升多种方式

ansible-playbook权限提升多种方式

Ansible-playbook 剧本编写

Ansible-playbook 剧本编写