Ansible基础 - 07playbook
Ansible基础 - 07playbook
一、概述
Playbook, 类似于saltstack的state状态文件。
ad-hoc无法持久使用,playbook可以持久使用。
playbook由一个或多个play组成的列表,play的主要功能: 将事先归并为一组的主机 装扮成 事先通过ansible中的task定义好的角色。
将多个play组织在一个playbook中, 可以让它们联合起来 按事先编排的机制完成某一任务。
Playbook是通过yml语法进行编排的。
### 结构:
- hosts: web
  vars:
    hello: Ansible
  tasks:
  - name: Configure Yum Repo
    yum_repository:
      name: nginx
      description: nginx repo
      baseurl: http://nginx.org/packages/centos/7/$basearch/
      gpgcheck: yes
      enabled: yes
  - name: Install Nginx
    yum: name=nginx state=present
  - name: Change Home
    copy: 
      content: "hello {{hello}}"
      dest: /var/www/html/index.html
  - name: Start Nginx 
    service: name=nginx state=started
二、定义变量和使用变量
2.1 在playbook文件直接定义变量
- hosts: web
  vars:
    web_pack: httpd-2.4.6
    ftp_pack: vsftpd
  tasks:
  - name: Install 
    yum:
      name:	
        - "{{ web_pack }}"
        - "{{ ftp_pack }}"  
      state: present
2.2 定义变量文件
[root@cl-server playbooks]# cat template-demo02.yml 
- hosts: cl-node02
  vars_files:
    - ./template-demo02-vars.yml
  tasks:
  - name: Install 
    yum:
      name:	
        - "{{ web_pack }}"
        - "{{ ftp_pack }}"  
      state: present
[root@cl-server playbooks]# cat template-demo02-vars.yml 
web_pack: httpd-2.4.6
ftp_pack: vsftpd
2.3 在主机清单文件中定义
[web]
192.168.234.6
[web:vars]
pack_name=httpd
2.4 定义 group_vars 和 host_vars目录
group_vars 为组定义的变量目录,其下的文件名为组名, 如 group_vars/web
host_vars 为主机定义的变量目录,其下的文件名为IP, 如 host_vars/192.168.234.12
默认情况下, group_vars目录中文件名与hosts清单的组名保持一致,系统还提供了一个特殊的组all,在group_vars中新建一个all文件,所有组都可使用。
[root@cl-server ansible]# vi hosts
[cl1]
cl-node01
[root@cl-server ansible]# cat /etc/ansible/group_vars/cl1.yml 
http_port: 9099
server_name: cl3.kunking.com
[root@cl-server ansible]# ansible cl1 -a "echo {{ server_name }}"
cl-node01 | CHANGED | rc=0 >>
cl3.kunking.com
[root@cl-server ansible]# ansible cl1 -a "echo {{ http_port }}"
cl-node01 | CHANGED | rc=0 >>
9099
2.5 执行playbook时使用-e参数指定变量
ansible-playbook httpd.yml -e "hosts=web" -e "pack_name=httpd"
[root@cl-server playbooks]# cat srv_install_module.yml 
---
- hosts: cl
  remote_user: root
  tasks:
    - name: install {{ rpmname }} package
      yum: name={{ rpmname }} state=present
    - name: copy {{ rpmname }} config
      copy: src=/root/playbooks/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
      notify: reload
      tags: reload{{ rpmname }}
    - name: start {{ rpmname }} service
      service: name={{ rpmname }} state=started enabled=true
      tags: start{{ rpmname }}
  handlers:
    - name: reload
      service: name={{ rpmname }} state=restarted
[root@cl-server playbooks]# ansible-playbook srv_install_module.yml -e rpmname=keepalived
[root@cl-server playbooks]# cat srv_install_module.yml 
---
- hosts: cl
  remote_user: root
  vars:
    - rpmname: nginx
      nginxport: 8888
  tasks:
    - name: install {{ rpmname }} package
      yum: name={{ rpmname }} state=present
    - name: copy {{ rpmname }} config
      template: src=/root/playbooks/{{ rpmname }}.conf.j2 dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
      notify: reload
      tags: reload{{ rpmname }}
    - name: start {{ rpmname }} service
      service: name={{ rpmname }} state=started enabled=true
      tags: start{{ rpmname }}
  handlers:
    - name: reload
      service: name={{ rpmname }} state=restarted
[root@cl-server playbooks]# cat nginx.conf.j2 
user nginx;
worker_processes {{ ansible_processor_vcpus }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
......
http {
    ......
    server {
        listen       {{ nginxport }};
        listen       [::]:{{ nginxport }};
        server_name  _;
        root         /usr/share/nginx/html;
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
    }
}
2.6 变量引入的顺序
- 1. 通过执行命令传递的变量
- 2. 在playbook中引入vars_files中的变量
- 3. 在playbook中定义的vars变量
- 4. 在host_vars中定义的变量
- 5. 在group_vars中组名文件中定义的变量
- 6. 在group_vars中all文件中定义的变量
2.7 ansible register 注册变量
[root@cl-server playbooks]# cat register-demo01.yml 
- hosts: cl-node02
  tasks:
  - name: install httpd server
    yum: name=httpd state=present
  - name: service httpd server
    service: name=httpd state=started enabled=yes
  - name: check httpd status
    shell: ps aux | grep httpd
    register: httpd_status
  - name: output httpd_status variable
    debug: 
      msg: "{{ httpd_status }}"
[root@cl-server playbooks]# ansible-playbook register-demo01.yml 
PLAY [cl-node02] ******************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************
TASK [install httpd server] *******************************************************************************************************************
TASK [service httpd server] *******************************************************************************************************************
TASK [check httpd status] *********************************************************************************************************************
TASK [output httpd_status variable] ***********************************************************************************************************
ok: [cl-node02] => {
    "msg": {
        "changed": true, 
        "cmd": "ps aux | grep httpd", 
        "delta": "0:00:00.014781", 
        "end": "2021-11-22 15:54:27.732964", 
        "failed": false, 
        "rc": 0, 
        "start": "2021-11-22 15:54:27.718183", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "root       4335  0.2  0.5 230440  5208 ?        Ss   15:54   0:00 /usr/sbin/httpd -DFOREGROUND\n ### 本身是一行,为了展示方便,换行
apache     4336  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND\n
apache     4337  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND\n
apache     4338  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND\n
apache     4339  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND\n
apache     4340  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND\n
root       4397  0.0  0.1 113280  1208 pts/1    S+   15:54   0:00 /bin/sh -c ps aux | grep httpd\n
root       4399  0.0  0.0 112824   964 pts/1    S+   15:54   0:00 grep httpd", 
        "stdout_lines": [
            "root       4335  0.2  0.5 230440  5208 ?        Ss   15:54   0:00 /usr/sbin/httpd -DFOREGROUND", 
            "apache     4336  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND", 
            "apache     4337  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND", 
            "apache     4338  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND", 
            "apache     4339  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND", 
            "apache     4340  0.0  0.2 230440  2980 ?        S    15:54   0:00 /usr/sbin/httpd -DFOREGROUND", 
            "root       4397  0.0  0.1 113280  1208 pts/1    S+   15:54   0:00 /bin/sh -c ps aux | grep httpd", 
            "root       4399  0.0  0.0 112824   964 pts/1    S+   15:54   0:00 grep httpd"
        ]
    }
}
PLAY RECAP ************************************************************************************************************************************
cl-node02                  : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
2.8 Ansible Facts变量
Gathering Facts: 获取目标主机的信息。
[root@cl-server playbooks]# ansible cl-node02 -m setup
[root@cl-server playbooks]# cat facts-demo01.yml 
- hosts: cl-node02
  tasks:
  - name: Query Host Info
    debug:
      msg: IP address is {{ansible_default_ipv4.address}} in hosts {{ansible_distribution}}
[root@cl-server playbooks]# ansible-playbook facts-demo01.yml 
PLAY [cl-node02] *************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************
ok: [cl-node02]
TASK [Query Host Info] *******************************************************************************************
ok: [cl-node02] => {
    "msg": "IP address is 192.168.234.12 in hosts CentOS"
}
PLAY RECAP *******************************************************************************************************
cl-node02                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
2.9 关闭ansible gather_facts
[root@cl-server playbooks]# cat facts-demo02.yml 
- hosts: cl-node02
  gather_facts: no
  tasks:
  - name: Install atop
    yum: name=atop state=present
[root@cl-server playbooks]# ansible-playbook facts-demo02.yml 
PLAY [cl-node02] *************************************************************************************************
TASK [Install atop] **********************************************************************************************
changed: [cl-node02]
PLAY RECAP *******************************************************************************************************
cl-node02                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
三、Task 任务控制
- 条件判断: when
- 循环语句: with_items
- 触发器: handlers
- 标签: tags
- 包含: include
- 忽略错误: ignore_error
- 错误处理: change
3.1 条件判断 when
[root@cl-server playbooks]# cat task_control_demo01.yml
- hosts: cl-node02
  tasks:
  - name: Install CentOS httpd
    yum: name=httpd state=present
    when: ( ansible_distribution  == "CentOS" )
  - name: Install Ubuntu httpd
    yum: name=httpd2 state=present
    when: ansible_distribution == "Ubuntu"
[root@cl-server playbooks]# ansible-playbook task_control_demo01.yml 
PLAY [cl-node02] ******************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************
ok: [cl-node02]
TASK [Install CentOS httpd] *******************************************************************************************************************
ok: [cl-node02]
TASK [Install Ubuntu httpd] *******************************************************************************************************************
skipping: [cl-node02]
PLAY RECAP ************************************************************************************************************************************
cl-node02                  : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
[root@cl-server playbooks]# cat task_control_demo02.yml
- hosts: cl-node02
  tasks:
  - name: check httpd server
    command: systemctl is-active httpd
    register: check_httpd
  - name: httpd restart
    service: name=httpd state=restarted
    when: check_httpd.rc == 0
3.2 循环语句 with_items
[root@cl-server playbooks]# cat task_control_demo03.yml 
- hosts: cl-node02
  tasks:
  - name: Service Start
    service: name={{item}} state=restarted
    with_items:
      - nginx
      - httpd
  - name: Copy Configure File
    copy: 
      src: "{{item.src}}"
      dest: "{{item.dest}}"
      mode: "{{item.mode}}"
    with_items:
      - {src: './nginx.conf', dest: '/etc/nginx/nginx.conf', mode: '0644'}
      - {src: './httpd.conf', dest: '/etc/httpd/httpd.conf', mode: '0755'}
[root@cl-server playbooks]# cat ex_item.yml 
- hosts: cl
  remote_user: root
  tasks:
  - name: install web packages
    yum: name={{ item }} state=present
    with_items:
    - telnet
    - htop
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via squash_actions is deprecated. Instead of 
using a loop to supply multiple items and specifying `name: "{{ item }}"`, please use `name: ['telnet', 'htop']` and
 remove the loop. This feature will be removed in version 2.11. Deprecation warnings can be disabled by setting 
deprecation_warnings=False in ansible.cfg.
[root@cl-server playbooks]# cat ex_item.yml 
- hosts: cl
  remote_user: root
  tasks:
  - name: install web packages
    yum: 
      name: ['telnet', 'htop', 'tree'] 
      state: present
	  
[root@cl-server playbooks]# ansible-playbook ex_item.yml 
3.3 触发器 handlers
当某个任务发生变化时,触发另一个任务的执行,例如httpd配置文件变更,触发httpd重启。
handler虽然是某个任务触发的,但是必须等到所有的task都执行完成后,才会被触发。如果在执行完成前,有另一个task任务执行失败了,那么被触发的handlers也不会被执行。
[root@cl-server playbooks]# cat task_control_demo04.yml 
- hosts: cl-node02
  tasks:
  - name: install httpd server
    yum: name=httpd state=present
  - name: configure httpd server
    copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
    notify: 
      - Restart Httpd Server
  - name: service httpd server
    service: name=httpd state=started enabled=yes 
  handlers:
  - name: Restart Httpd Server
    service: name=httpd state=restarted
[root@cl-server playbooks]# ansible-playbook task_control_demo04.yml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [install httpd server] ****************************************************************************************************
ok: [cl-node02]
TASK [configure httpd server] **************************************************************************************************
changed: [cl-node02]
TASK [service httpd server] ****************************************************************************************************
ok: [cl-node02]
RUNNING HANDLER [Restart Httpd Server] *****************************************************************************************
changed: [cl-node02]
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
### 测试触发时机
[root@cl-server playbooks]# cat task_control_demo05.yml 
- hosts: cl-node02
  tasks:
  - name: install httpd server
    yum: name=httpd state=present
  - name: before notify
    copy: src=/root/aa.txt dest=/tmp/aa.txt
  - name: configure httpd server
    copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
    notify: 
      - Restart Httpd Server
  - name: after notify
    copy: src=/root/aa.conf dest=/tmp/aa.txt
  - name: service httpd server
    service: name=httpd state=started enabled=yes 
  handlers:
  - name: Restart Httpd Server
    service: name=httpd state=restarted
当 before notify 执行失败, 不会触发。
当 before notify 执行成功, after notify 执行失败, 文件会更新,不会触发。
修正错误后, 继续执行,也不会触发,因为配置文件没有更新。
3.4 tags标签
使用ansible-playbook 执行时可以指定标签来执行任务,不必执行所有任务。
标签: 1.一个任务设置一个标签, 2.一个任务设置多个标签,3.多个任务设置一个标签
[root@cl-server playbooks]# cat task_control_demo06.yml 
- hosts: cl-node02
  tasks:
  - name: install httpd server
    yum: name=httpd state=present
    tags: install
  - name: configure httpd server
    copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
    notify: 
      - Restart Httpd Server
    tags: configure
  - name: after notify
    copy: src=/root/aa.txt dest=/tmp/aa.txt
    tags: ["touch_aa", "install"]
  - name: service httpd server
    service: name=httpd state=started enabled=yes
    tags: start 
  handlers:
  - name: Restart Httpd Server
    service: name=httpd state=restarted
[root@cl-server playbooks]# ansible-playbook task_control_demo06.yml -t "configure"
[root@cl-server playbooks]# ansible-playbook task_control_demo06.yml -t "configure,touch_aa"
[root@cl-server playbooks]# ansible-playbook task_control_demo06.yml --skip-tags "install"
[root@cl-server playbooks]# ansible-playbook task_control_demo06.yml -t "install"
3.5 include
把任务单独写在一个yaml文件中,其他任务需要时通过include_tasks:xxx.yaml引入。
[root@cl-server playbooks]# cat task_control_include01.yml 
- name: restart httpd service
  service: name=httpd state=restarted
[root@cl-server playbooks]# cat task_control_include02.yml 
- hosts: cl-node02
  tasks:
  - name: configure httpd server
    copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
  - name: restart httpd server
    include_tasks: ./task_control_include01.yml 
[root@cl-server playbooks]# ansible-playbook task_control_include02.yml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [configure httpd server] **************************************************************************************************
ok: [cl-node02]
TASK [restart httpd server] ****************************************************************************************************
included: /root/playbooks/task_control_include01.yml for cl-node02
TASK [restart httpd service] ***************************************************************************************************
changed: [cl-node02]
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
把两个完整的playbook合并, 按照顺序先后执行
[root@cl-server playbooks]# cat task_control_include03.yml 
- hosts: cl-node02
  tasks:
  - name: install httpd server
    yum: name=httpd state=present
[root@cl-server playbooks]# cat task_control_include04.yml 
- hosts: cl-node02
  tasks:
  - name: configure httpd server
    copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
	
[root@cl-server playbooks]# cat task_control_include05.yml 
- import_playbook: ./task_control_include03.yml
- import_playbook: ./task_control_include04.yml
[root@cl-server playbooks]# ansible-playbook task_control_include05.yml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [install httpd server] ****************************************************************************************************
ok: [cl-node02]
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [configure httpd server] **************************************************************************************************
ok: [cl-node02]
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
3.6 忽略错误ignore_errors
在执行playbook时,如果其中某个任务失败了,它后面的任务就不会再执行了。
如果某些任务是可以执行失败的,需要失败后继续执行后续任务,添加ignore_errors。
[root@cl-server playbooks]# cat ignore_error.yml 
- hosts: cl-node02
  tasks:
  - name: check httpd status
    command: ps aux | grep httpd
    register: httpd_status
    ignore_errors: yes
  - name: restart httpd
    service: name=httpd state=restarted
[root@cl-server playbooks]# ansible-playbook ignore_error.yml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [check httpd status] ******************************************************************************************************
fatal: [cl-node02]: FAILED! => {"changed": true, "cmd": ["ps", "aux", "|", "grep", "httpd"], "delta": "0:00:00.006600", "end": "2021-11-22 17:22:39.989640", 
"msg": "non-zero return code", "rc": 1, "start": "2021-11-22 17:22:39.983040", "stderr": "error: garbage option\n\nUsage:\n ps [options]\n\n 
Try 'ps --help '\n  or 'ps --help '\n for additional help text.\n\nFor more details see ps(1).", 
"stderr_lines": ["error: garbage option", "", "Usage:", " ps [options]", "", " Try 'ps --help '", "  
or 'ps --help '", " for additional help text.", "", "For more details see ps(1)."], "stdout": "", "stdout_lines": []}
...ignoring
TASK [restart httpd] ***********************************************************************************************************
changed: [cl-node02]
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   
  
3.7 错误处理
3.7.1 force_handlers: yes 强制调用handlers。
只要handlers被触发,无论是否有任务执行失败,均调用handlers。
[root@cl-server playbooks]# cat error_handler01.yaml 
- hosts: cl-node02
  force_handlers: yes
  tasks:
  - name: configure httpd server
    copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
    notify: 
      - Restart Httpd Server
  - name: after notify
    copy: src=/root/aa.conf dest=/tmp/aa.txt
  - name: service httpd server
    service: name=httpd state=started enabled=yes 
  handlers:
  - name: Restart Httpd Server
    service: name=httpd state=restarted
[root@cl-server playbooks]# ansible-playbook error_handler01.yaml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [configure httpd server] **************************************************************************************************
changed: [cl-node02]
TASK [after notify] ************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: If you are using a module and expect the file to exist on the remote, 
see the remote_src option fatal: [cl-node02]: FAILED! => {"changed": false, "msg": "Could not find or access '/root/aa.conf' on the Ansible Controller.\n
If you are using a module and expect the file to exist on the remote, see the remote_src option"}
RUNNING HANDLER [Restart Httpd Server] *****************************************************************************************
changed: [cl-node02]
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=3    changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  
3.7.2 changed_when
当任务执行时,被控主机端发生了变化,change就会变化,但是某些命令,只是查询信息,没有修改,但一直会显示change状态。可以强制把change状态关掉。
[root@cl-server playbooks]# cat error_handler02.yaml 
- hosts: cl-node02
  tasks:
  - name: test task
    shell: ps aux
    changed_when: False
### 添加 changed_when 前
[root@cl-server playbooks]# ansible-playbook error_handler02.yaml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [test task] ***************************************************************************************************************
changed: [cl-node02]
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
### 添加 changed_when: False后
[root@cl-server playbooks]# ansible-playbook error_handler02.yaml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [test task] ***************************************************************************************************************
ok: [cl-node02]
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[root@cl-server playbooks]# cat error_handler03.yml 
- hosts: cl-node02
  tasks:
  - name: install nginx server
    yum: name=nginx state=present
  - name: configure nginx
    copy: src=./nginx.conf dest=/etc/nginx/nginx.conf
  - name: check nginx configure
    command: /usr/sbin/nginx -t
    register: check_nginx
  - name: service nginx server
    service: name=nginx state=restarted
    changed_when: ( check_nginx.stdout.find('successful') )
[root@cl-server playbooks]# ansible-playbook error_handler03.yml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [install nginx server] ****************************************************************************************************
ok: [cl-node02]
TASK [configure nginx] *********************************************************************************************************
ok: [cl-node02]
TASK [check nginx configure] ***************************************************************************************************
changed: [cl-node02]
TASK [service nginx server] ****************************************************************************************************
changed: [cl-node02]
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
### 修改 配置文件, nginx配置文件检查失败, 重启检查失败,不再重启
[root@cl-server playbooks]# ansible-playbook error_handler03.yml 
PLAY [cl-node02] ***************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [cl-node02]
TASK [install nginx server] ****************************************************************************************************
ok: [cl-node02]
TASK [configure nginx] *********************************************************************************************************
changed: [cl-node02]
TASK [check nginx configure] ***************************************************************************************************
fatal: [cl-node02]: FAILED! => {"changed": true, "cmd": ["/usr/sbin/nginx", "-t"], "delta": "0:00:00.008670", "end": "2021-11-22 17:55:48.681369", 
"msg": "non-zero return code", "rc": 1, "start": "2021-11-22 17:55:48.672699", 
"stderr": "nginx: [emerg] unknown directive \"adad\" in /etc/nginx/nginx.conf:5\nnginx: configuration file /etc/nginx/nginx.conf test failed",
"stderr_lines": ["nginx: [emerg] unknown directive \"adad\" in /etc/nginx/nginx.conf:5", "nginx: configuration file /etc/nginx/nginx.conf test failed"],
"stdout": "", "stdout_lines": []}
PLAY RECAP *********************************************************************************************************************
cl-node02                  : ok=3    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 
四、PLAYBOOK案例
[root@cl-server playbooks]# cat ex_copy.yml 
---
- name: test copy / fetch / user / group
  hosts: cl
  remote_user: root
  tasks:
    - name: test copy
      copy:
        src: ~/df.sh
        dest: /tmp/df.sh
    - name: unarchive tar.gz
      unarchive:
        src: ~/apache-tomcat-8.5.65.tar.gz
        dest: /tmp/
    - name: create group
      group: name=testadmin
    - name: create user
      user: name=admin01 group=testadmin
    - name: sync
      synchronize:
        src: ~/tt.txt
        dest: /tmp/tt.txt
        archive: no
        recursive: yes
    - name: install ncat
      yum: name=sl
[root@cl-server playbooks]# ansible-playbook ex_copy.yml
[root@cl-server playbooks]# cat nginx_v2.yml 
---
- hosts: cl
  remote_user: root
  tasks:
    - name: install nginx package
      yum: name=nginx state=present
    - name: copy nginx config
      copy: src=/root/playbooks/nginx_v2.conf  dest=/etc/nginx/nginx.conf  backup=yes
      notify: reload
      tags: reloadnginx
    - name: start nginx service
      service: name=nginx state=started enabled=true
      tags: startnginx
  handlers:
    - name: reload
      service: name=nginx state=restarted