# Ansible Task Control

# 1.Ansible Task Control

# 1.1 when 条件语句

when 关键字主要针对 TASK 任务进行判断,对于此前我们使用过的 yum 模块是可以自动检测软件包是否已被安装,无需人为干涉;但对于有些任务则是需要进行判断才可以实现的。

  • 比如:web 节点都需要配置 nginx 仓库,但其他节点并不需要,此时就会用到 when 判断。
  • 比如: Centos 与 Ubuntu 都需要安装 Apache,而 Centos 系统软件包为 httpd,而 Ubuntu 系统软件包为 httpd2,那么此时就需要判断主机系统,然后为不同的主机系统安装不同的软件包。
# 1.1.1 案例 1 - 根据不同操作系统安装相同的软件

需求:为所有主机安装 Apache 软件

  • 系统为 CentOS:安装 httpd
  • 系统为 Ubuntu:安装 httpd2

1. 通过 fact 变量判断系统

[root@manager task]# ansible localhost -m setup | less
...
        "ansible_distribution": "CentOS", 
...

2. 编写 playbook 文件

[root@manager task]# cat task_when.yml 
- hosts: webservers
  tasks:
    
    - name: Centos Install httpd # 通过 fact 变量判断系统为 centos 才会安装 httpd
      yum: 
        name: httpd
        state: present
      when: (ansible_distribution == "CentOS")
    - name: Ubuntu Install httpd # 通过 fact 变量判断系统为 ubuntu 才会安装 httpd2
      yum: 
        name: apache2
        state: present
      when: (ansible_distribution == "Ubuntu")

3. 执行 playbook

[root@manager task]# ansible-playbook task_when.yml
# 1.1.2 案例 2 - 为特定的主机添加 Nginx 仓库

为所有主机添加 Nginx 仓库

  • 主机名为 web:添加 Nginx 仓库
  • 主机名不为 web:不做任何处理

1. 编写 playbook 文件

[root@manager task]# cat task_when_2.yml 
- hosts: all
  tasks:
  - name: Add Nginx Yum Repository
    yum_repository:
      name: ansible_web_nginx
      description: Nginx Repository
      baseurl: http://nginx.org/packages/centos/7/$basearch/
      gpgcheck: no
    when: (ansible_hostname is match("web*"))
#    when: (ansible_hostname is match("web*")) or (ansible_hostname is match("lb*"))
# 当然 when 也可以使用 and 与 or 方式
# when: (ansible_hostname is match("web*")) or (ansible_hostname is match("lb*"))

2. 执行 playbook

[root@manager task]# ansible-playbook task_when_2.yml
# 1.1.3 案例 3 - 判断服务是否正常运行

判断 Nginx 服务是否处于运行状态

  • 已运行:则重启服务
  • 未运行:则不做处理

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

[root@manager task]# cat task_when_3.yml 
- hosts: webservers
  tasks:
    - name: Get Nginx Server Status
      shell: 
        cmd: systemctl status nginx &>/dev/null
      register: Nginx_Check
    - name: Debug
      debug:
        msg: ""
    - name: Restart Ngxin Server
      systemd:
        name: nginx
        state: restarted
      when: Nginx_Check.rc == 0

2. 执行 playbook

[root@manager task]# ansible-playbook task_when_3.yml
# 1.1.4 案例 4 - 为特定的主机执行任务

有 2 台 server

  • 第一台:192.168.1.7 安装了 nginx
  • 第二台:192.168.1.51 没有安装 nginx

现在需要在没有安装 nginx 的节点上做操作创建文件,需要通过 when 条件语句实现

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

[root@manager task]# cat task_when_4.yml 
- hosts: all
  tasks:
    - name: Get System Install Nginx
      shell:
        cmd: rpm -qa nginx | wc -l
      register: get_nginx
    - name: Debug
      debug:
        msg: ""
    - name: Create Nginx File
      file:
        path: /tmp/nginx_not_install.txt
        state: touch
      when: get_nginx.stdout == '0'

2. 执行 playbook 并测试

[root@manager task]# ansible-playbook task_when_4.yml
[root@db01 ~]# ll /tmp/nginx_not_install.txt 
-rw-r--r-- 1 root root 0 Oct 29 11:00 /tmp/nginx_not_install.txt
# 1.2 loop 循环语句

在写 playbook 的时候发现了很多 task 都要重复引用某个相同的模块,比如一次启动 10 个服务,或者一次拷贝 10 个文件,如果按照传统的写法最少要写 10 次,这样会显得 playbook 很臃肿。如果使用循环的方式来编写 playbook,这样可以减少重复编写 task 带来的臃肿;

# 1.2.1 案例 1 - 使用循环批量启动服务

1. 在没有使用循环的场景下,启动多个服务需要写多条 task 任务。

[root@manager ~]# cat loop_1-1.yml 
- hosts: webservers
  tasks:
    - name: Systemd Nginx
      systemd:
        name: nginx
        state: started
    - name: Systemd PHP
      systemd:
        name: php-fpm
        state: started

2. 我们将如上的 playbook 修改为循环的方式,减少重复编写多条 task 任务。

[root@manager ~]# cat loop_1.yml 
- hosts: webservers
  tasks:
    - name: Systemd Nginx php
      systemd:
        name: ""
        state: started
      loop:
        - nginx
        - php-fpm

3. 执行 playbook

[root@manager ~]# ansible-playbook loop_1.yml
# 1.2.2 案例 2 - 使用循环批量安装软件

1. 批量安装软件

[root@manager ~]# cat loop_2.yml 
- hosts: webservers
  tasks:
    - name: Installed Httpd Mariadb Package
      yum: 
        name: ""
        state: latest
      loop:
         - httpd
         - mariadb-server

2. 执行 playbook

[root@manager ~]# ansible-playbook loop_2.yml
# 1.2.3 案例 3 - 使用循环批量拷贝文件

1. 批量拷贝文件,使用 key values 字典的方式

[root@manager ~]# cat loop_3.yml 
- hosts: webservers
  tasks:
    - name: Rsync rsyncd.conf
      copy:
        src: ""
        dest: ""
        owner: root
        group: root
        mode: ""
      loop:
        - { src: rsyncd.conf , dest: /tmp/rsyncd.conf , mode: "0644"  }
        - { src: rsyncd.pass , dest: /root/rsync.pass , mode: "0600" }
        - { src: rsynnd.test , dest: /mnt/rsync.test , mode: "0000" }

2. 执行 playbook 并验证

[root@manager ~]# ansible-playbook loop_3.yml 
[root@web_7 ~]# ll /tmp/rsyncd.conf
-rw-r--r-- 1 root root 0 Oct 29 20:01 /tmp/rsyncd.conf
[root@web_7 ~]# ll /root/rsync.pass
-rw------- 1 root root 0 Oct 29 20:03 /root/rsync.pass
[root@web_7 ~]# ll /mnt/rsync.test
---------- 1 root root 0 Oct 29 20:02 /mnt/rsync.test
# 1.2.4 案例 4 - 使用循环批量创建用户

1. 批量创建用户,使用 key values 字典的方式

[root@manager ~]# cat loop_4.yml 
- hosts: webservers
  tasks:
    - name: Add Users
      user: 
        name: ""
        groups: ""
        state: present
      loop:
        - { name: 'testuser1', groups: 'bin' }
        - { name: 'testuser2', groups: 'root' }

2. 执行 playbook

[root@manager ~]# ansible-playbook loop_4.yml
[root@web_7 ~]# id testuser1
uid=1001(testuser1) gid=1001(testuser1) groups=1001(testuser1),1(bin)
# 1.2.5 案例 5 - 使用循环批量创建目录

1. 批量创建目录,使用 key values 字典的方式

[root@manager ~]# cat loop_5.yml 
- hosts: webservers
  tasks:
    - name: Create /data /backup
      file:
        path: ""
        state: directory
      loop:
        - /data
        - /backup
        - /ttt

2. 执行 playbook

[root@manager ~]# ansible-playbook loop_5.yml 
[root@web_7 ~]# ll /data
total 0
[root@web_7 ~]# ll /backup/
total 4
-rw-r--r-- 1 www www 1160 Oct 25 22:04 install_rsync_server.yml
[root@web_7 ~]# ll /ttt/
total 0
# 1.3.Handlers 与 Notify

Handlers 是一个触发器,同时是一个特殊的 tasks,它无法直接运行,它需要被 tasks 通知后才会运行。比如:httpd 服务配置文件发生变更,我们则可通过 Notify 通知给指定的 handlers 触发器,然后执行相应重启服务的操作,如果配置文件不发生变更操作,则不会触发 Handlers 任务的执行;

# 1.3.1 案例 1 - 变更服务配置触发重启
[root@manager web_cluster]# cat redis_server.yml 
- hosts: dbservers
  tasks:
    - name: Installed Redis Server
      yum:
        name: redis
        state: present
    - name: Configure Redis Server
      copy:
        src: ./files/redis.conf.j2
        dest: /etc/redis.conf
        owner: redis
        group: root
        mode: 0640
      notify: Restart Redis Server
    - name: Systemd Redis Server
      systemd:
        name: redis
        state: started
        enabled: yes
  handlers:
    - name: Restart Redis Server
      systemd:
        name: redis
        state: restarted
# 1.3.2 Handlers 注意事项与说明

handlers 注意事项:

  • 1. 无论多少个 task 通知了相同的 handlers,handlers 仅会在所有 tasks 结束后运行一次。
  • 2. 只有 task 发生改变了才会通知 handlers ,没有改变则不会触发 handlers
  • 3. 不能使用 handlers 替代 tasks、因为 handlers 是一个特殊的 tasks
# 1.4 tags 任务标签

默认情况下,Ansible 在执行一个 playbook 时,会执行 playbook 中所有的任务。而标签功能是用来指定要运行 playbook 中的某个特定的任务;

1. 为 playbook 添加标签的方式有如下几种:

  • 对一个 task 打一个标签
  • 对一个 task 打多个标签
  • 对多个 task 打一个标签

2.task 打完标签使用的几种方式

  • -t 执行指定 tag 标签对应的任务
  • --skip-tags 执行除 --skip-tags 标签之外的所有任务
# 1.4.1 案例 1 - 指定执行某个 tags

1. 给 playbook 指定的 task 打 tags 标签

[root@manager ~]# cat install_nfs_server.yml 
- hosts: webservers
  tasks:
    - name: 1.Installed NFS Server
      yum:
        name: nfs-utils
        state: present
      tags:
        - install_nfs
        - install_nfs-server
    - name: 2.Configure NFS Server
      copy:
        src: ./exports.j2
        dest: /etc/exports
      notify: Restart NFS Server
    - name: 3.Init Group 
      group:
        name: www
        gid: 666
    - name: 4.Init User
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: no
      tags: Configure_nfs-server
        
    - name: 5.Init Create Directory
      file:
        path: /data
        state: directory
        owner: www
        group: www
        mode: "0755"
      tags: Configure_nfs-server
    - name: 6.Started NFS Server
      systemd:
        name: nfs
        state: started
        enabled: yes
  handlers:
    - name: Restart NFS Server
      systemd:
        name: nfs
        state: restarted

2. 使用 -t 执行指定的 tags 标签对应的任务

[root@manager ~]# ansible-playbook install_nfs_server.yml  -t Configure_nfs-server
# 1.4.2 案例 2 - 指定排除某个 tags
[root@manager ~]# ansible-playbook install_nfs_server.yml  --skip-tag install_nfs-server
# 1.5 include 任务复用

有时,我们发现大量的 Playbook 内容需要重复编写,各 Tasks 之间功能需相互调用才能完成各自功能,Playbook 庞大到维护困难,这时我们需要使用 include

比如:A 项目需要用到重启 httpd,B 项目需要用到,重启 httpd,那么我们可以使用 Include 来减少重复编写

# 1.5.1 案例 1 - 多个项目调用相同 task

1. 编写 restart_nginx.yml 文件

# 注意这是一个 tasks 所有没有 play 的任何信息
[root@manager ~]# cat task_restart_nginx.yml 
- name: Restart Nginx Server
  systemd:
    name: nginx
    state: restarted

2.A Project 的 playbook 如下

[root@manager ~]# cat task_a_project.yml 
- hosts: webservers
  tasks:
    - name: A Project
      command: echo "a"
    - name: Restart Nginx
      include: ./task_restart_nginx.yml

3.B Project 的 playbook 如下

[root@manager ~]# cat task_b_project.yml 
- hosts: webservers
  tasks:
    - name: B Project
      command: echo "b"
    - name: Restart Nginx
      include: ./task_restart_nginx.yml

4.A Project 和 B Project 执行后的测试结果如下

[root@manager ~]# ansible-playbook task_a_project.yml 
[root@manager ~]# ansible-playbook task_b_project.yml
# 1.5.2 案例 2-Inlcude 结合 tags 应用

通过指定标签 tags,来说明是安装 tomcat8 还是 tomcat9

  • 1. 准备入口 main.yml 文件,然后包含 install_tomcat8.yml 以及 install_tomcat9.yml
  • 2. 在执行 main.yml 时,需要通过 --tags 指明要安装的版本

1. 编写 main.yml 入口文件

[root@manager ~]# cat main.yml 
- name: Install Tomcat8 Server
  include: install_tomcat_8.yml
  tags: install_tomcat_8
- name: Install Tomcat9 Server
  include: install_tomcat_9.yml
  tags: install_tomcat_9

2. 编写 install_tomcat8.yml

[root@manager task]# cat install_tomcat_8.yml
- hosts: webservers
  vars:
    - tomcat_data: /data
    - tomcat_version: 8.5.70
  tasks:
    - name: Create Tomcat Directory
      file:
        name: ""
        state: directory
    
    - name: Copy Tomcat Server
      unarchive:
        src: "./files/apache-tomcat-.tar.gz"
        dest: ""
    
    - name: Create Links
      file:
        src: "/apache-tomcat-"
        dest: "/tomcat8"
        state: link
    
    - name: Started Tomcat Server
      shell:
        cmd: "nohup /tomcat8/bin/startup.sh &>/dev/null &"

3. 编写 install_tomcat9.yml

[root@manager task]# cat install_tomcat_9.yml 
- hosts: webservers
  vars:
    - tomcat_data: /data
    - tomcat_version: 9.0.53
  tasks:
    - name: Create Tomcat Directory
      file:
        name: ""
        state: directory
    
    - name: Copy Tomcat Server
      unarchive:
        src: "./files/apache-tomcat-.tar.gz"
        dest: ""
    
    - name: Create Links
      file:
        src: "/apache-tomcat-"
        dest: "/tomcat9"
        state: link
    
    - name: Started Tomcat Server
      shell:
        cmd: "nohup /tomcat9/bin/startup.sh &>/dev/null &"

4. 安装 tomcat 安装包

[root@manager task]# ll files/
total 21628
-rw-r--r-- 1 root root 10564666 Oct 30 10:44 apache-tomcat-8.5.70.tar.gz
-rw-r--r-- 1 root root 11575393 Oct 30 10:44 apache-tomcat-9.0.53.tar.gz

5. 执行 main.yml 文件,然后通过 --tags 执行对应的版本

[root@manager task]# ansible-playbook main.yml --tags install_tomcat_8
[root@manager task]# ansible-playbook main.yml --tags install_tomcat_9
# 1.6 Playbook 异常处理
# 1.6.1 案例 1-Playbook 错误忽略

在 playbook 执行的过程中,难免会遇到一些错误。由于 playbook 遇到错误后,不会执行之后的任务,不便于调试,此时,可以使用 ignore_errors 来暂时忽略错误,使得 playbook 继续执行。

1. 编写 playbook,当有 task 执行失败则会立即终止后续 task 运行

[root@manager task]# cat task_error_1.yml 
- hosts: webservers
  remote_user: root
  tasks:
    - name: Ignore False
      command: /bin/false
#      ignore_errors: yes
    - name: touch new file
      file: path=/tmp/oldxu_ignore state=touch

2. 执行 playbook,会报错,后续的任务也没有执行。

[root@manager task]# ansible-playbook task_error_1.yml 
PLAY [webservers] ********************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.1.7]
ok: [192.168.1.8]
TASK [Ignore False] ******************************************************************************************************************
fatal: [192.168.1.8]: FAILED! => {"changed": true, "cmd": ["/bin/false"], "delta": "0:00:00.002689", "end": "2025-10-30 11:09:51.210356", "msg": "non-zero return code", "rc": 1, "start": "2025-10-30 11:09:51.207667", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
fatal: [192.168.1.7]: FAILED! => {"changed": true, "cmd": ["/bin/false"], "delta": "0:00:00.002650", "end": "2025-10-30 11:09:47.189233", "msg": "non-zero return code", "rc": 1, "start": "2025-10-30 11:09:47.186583", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
PLAY RECAP ***************************************************************************************************************************
192.168.1.7                : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
192.168.1.8                : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

3. 再次执行 playbook 如果碰到指定的 tasks 错误,会自动忽略,继续执行剩下的 tasks

[root@manager task]# cat task_error_1.yml 
- hosts: webservers
  remote_user: root
  tasks:
    - name: Ignore False
      command: /bin/false
      ignore_errors: yes
    - name: touch new file
      file: path=/tmp/oldxu_ignore state=touch
[root@manager task]# ansible-playbook task_error_1.yml 
[root@web01 ~]# ll /tmp/oldxu_ignore 
-rw-r--r-- 1 root root 0 Oct 30 11:10 /tmp/oldxu_ignore
# 1.6.2 案例 2-task 执行失败强制调用 handlers

通常情况下,当 task 失败后,play 将会终止,任何在前面已经被 tasks notify 的 handlers 都不会被执行。如果你在 play 中设置了 force_handlers: yes 参数,被通知的 handlers 就会被强制执行。(有些特殊场景可能会使用到)

1. 编写 playbook

[root@manager task]# cat task_error_2.yml 
- hosts: webservers
  force_handlers: yes
  tasks:
    - name: Create
      file:
        path: /tmp/test.txt
        state: touch
      notify: Restart Nginx Server
    - name: Installed Packages
      yum:
        name: xxxxx
        state: present
  handlers:
    - name: Restart Nginx Server
      systemd:
        name: nginx
        state: restarted

2. 执行 playbook

[root@manager task]# ansible-playbook task_error_2.yml 
PLAY [webservers] ********************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.1.7]
ok: [192.168.1.8]
TASK [Create] ************************************************************************************************************************
changed: [192.168.1.7]
changed: [192.168.1.8]
TASK [Installed Packages] ************************************************************************************************************
fatal: [192.168.1.8]: FAILED! => {"changed": false, "msg": "No package matching 'xxxxx' found available, installed or updated", "rc": 126, "results": ["No package matching 'xxxxx' found available, installed or updated"]}
fatal: [192.168.1.7]: FAILED! => {"changed": false, "msg": "No package matching 'xxxxx' found available, installed or updated", "rc": 126, "results": ["No package matching 'xxxxx' found available, installed or updated"]}
#前者 task 报错,也不影响 handlers 的调用
RUNNING HANDLER [Restart Nginx Server] ***********************************************************************************************
changed: [192.168.1.7]
changed: [192.168.1.8]
PLAY RECAP ***************************************************************************************************************************
192.168.1.7                : ok=3    changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
192.168.1.8                : ok=3    changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
# 1.6.3 案例 3 - 控制 Tasks 报告状态为 OK

1. 编辑 playbook

[root@manager task]# cat task_error_3.yml 
- hosts: webservers
  tasks:
    - name: Get Network Port 
      shell: netstat -lntp
      register: System_Port
#      changed_when: false
    - name: debug 
      debug:
        msg: 
          - "执行了  命令"
          - ""

2. 执行 playbook 会发现第一个 task 运行 shell 模块报告的改变,即使它没有真正的在远端系统做出改变,如果你一直运行,它会一直处在改变状态。

[root@manager task]# ansible-playbook task_error_3.yml 
PLAY [webservers] ********************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.1.8]
ok: [192.168.1.7]
TASK [Get Network Port] **************************************************************************************************************
changed: [192.168.1.7]
changed: [192.168.1.8]
TASK [debug] *************************************************************************************************************************
ok: [192.168.1.7] => {
    "msg": [
        "执行了 netstat -lntp 命令", 
        [
            "Active Internet connections (only servers)", 
            "Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    ", 
            "tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      5481/php-fpm: maste ", 
            "tcp        0      0 192.168.1.7:6379        0.0.0.0:*               LISTEN      15391/redis-server  ", 
            "tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      15391/redis-server  ", 
            "tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      5195/rpcbind        ", 
            "tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      26839/nginx: master ", 
            "tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      5478/sshd           ", 
            "tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      5683/master         ", 
            "tcp6       0      0 :::111                  :::*                    LISTEN      5195/rpcbind        ", 
            "tcp6       0      0 :::8080                 :::*                    LISTEN      11274/java          ", 
            "tcp6       0      0 :::22                   :::*                    LISTEN      5478/sshd           ", 
            "tcp6       0      0 ::1:25                  :::*                    LISTEN      5683/master         ", 
            "tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      11274/java          "
        ]
    ]
}
ok: [192.168.1.8] => {
    "msg": [
        "执行了 netstat -lntp 命令", 
        [
            "Active Internet connections (only servers)", 
            "Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    ", 
            "tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      5483/php-fpm: maste ", 
            "tcp        0      0 192.168.1.8:6379        0.0.0.0:*               LISTEN      26005/redis-server  ", 
            "tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      26005/redis-server  ", 
            "tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      5163/rpcbind        ", 
            "tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      32740/nginx: master ", 
            "tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      5481/sshd           ", 
            "tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      5693/master         ", 
            "tcp6       0      0 :::111                  :::*                    LISTEN      5163/rpcbind        ", 
            "tcp6       0      0 :::8080                 :::*                    LISTEN      31200/java          ", 
            "tcp6       0      0 :::22                   :::*                    LISTEN      5481/sshd           ", 
            "tcp6       0      0 ::1:25                  :::*                    LISTEN      5693/master         ", 
            "tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      31200/java          "
        ]
    ]
}
PLAY RECAP ***************************************************************************************************************************
192.168.1.7                : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.1.8                : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3.shell 任务不应该每次都报告 changed 状态,因为它没有在被管理主机执行后发生变化。添加 changed_when: false 来抑制这个改变

[root@manager task]# cat task_error_3.yml 
- hosts: webservers
  tasks:
    - name: Get Network Port 
      shell: netstat -lntp
      register: System_Port
      changed_when: false
    - name: debug 
      debug:
        msg: 
          - "执行了  命令"
          - ""

4. 再次执行 playbook

[root@manager task]# ansible-playbook task_error_3.yml 
PLAY [webservers] ********************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.1.8]
ok: [192.168.1.7]
TASK [Get Network Port] **************************************************************************************************************
ok: [192.168.1.8]
ok: [192.168.1.7]
TASK [debug] *************************************************************************************************************************
ok: [192.168.1.7] => {
    "msg": [
        "执行了 netstat -lntp 命令", 
        [
            "Active Internet connections (only servers)", 
            "Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    ", 
            "tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      5481/php-fpm: maste ", 
            "tcp        0      0 192.168.1.7:6379        0.0.0.0:*               LISTEN      15391/redis-server  ", 
            "tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      15391/redis-server  ", 
            "tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      5195/rpcbind        ", 
            "tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      26839/nginx: master ", 
            "tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      5478/sshd           ", 
            "tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      5683/master         ", 
            "tcp6       0      0 :::111                  :::*                    LISTEN      5195/rpcbind        ", 
            "tcp6       0      0 :::8080                 :::*                    LISTEN      11274/java          ", 
            "tcp6       0      0 :::22                   :::*                    LISTEN      5478/sshd           ", 
            "tcp6       0      0 ::1:25                  :::*                    LISTEN      5683/master         ", 
            "tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      11274/java          "
        ]
    ]
}
ok: [192.168.1.8] => {
    "msg": [
        "执行了 netstat -lntp 命令", 
        [
            "Active Internet connections (only servers)", 
            "Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    ", 
            "tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      5483/php-fpm: maste ", 
            "tcp        0      0 192.168.1.8:6379        0.0.0.0:*               LISTEN      26005/redis-server  ", 
            "tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      26005/redis-server  ", 
            "tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      5163/rpcbind        ", 
            "tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      32740/nginx: master ", 
            "tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      5481/sshd           ", 
            "tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      5693/master         ", 
            "tcp6       0      0 :::111                  :::*                    LISTEN      5163/rpcbind        ", 
            "tcp6       0      0 :::8080                 :::*                    LISTEN      31200/java          ", 
            "tcp6       0      0 :::22                   :::*                    LISTEN      5481/sshd           ", 
            "tcp6       0      0 ::1:25                  :::*                    LISTEN      5693/master         ", 
            "tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      31200/java          "
        ]
    ]
}
PLAY RECAP ***************************************************************************************************************************
192.168.1.7                : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.1.8                : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
# 1.6.4 案例 4-changed_when 检查任务结果

1. 编写 playbook,Nginx 具备配置文件健康检查功能;

[root@manager task]# cat task_error_4.yml 
- hosts: webservers
  tasks:
    - name: Configure Nginx Server
      template: 
        src: ./nginx.conf.j2 
        dest: /etc/nginx/nginx.conf
      notify: Restart Nginx Server
    - name: Check Nginx Server
      shell: /usr/sbin/nginx -t
      register: check_nginx
      changed_when: 
        # 查找变量返回的结果是否有 ok,如不存在则终止该 tasks
        - check_nginx.stderr.find('successful') 
        - false 
    - name: Debug
      debug:
        msg: ""
    - name: Systemd Nginx Server
      systemd:
        name: nginx
        state: started
  handlers:
    - name: Restart Nginx Server
      systemd:
        name: nginx
        state: restarted

2. 编写 playbook 配置文件

[root@manager task]# cat nginx.conf.j2 
user www;
worker_processes  2;
error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" "$http_x_via"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
}

3. 验证测试

[root@manager task]# ansible-playbook task_error_4.yml

# 2.Ansible vault

# 2.1AnsibleVault 概述

Ansib1eVault 可以将敏感的数据文件进行加密,而非存放在明文的 playbooks 中;
比如:部分 playbook 内容中有明文密码信息,可以对其进行加密操作;后期只有输入对应的密码才可以查
看、编辑或执行该文件,如没有密码则无法正常运行;

# 2.2AnsibleVault 应用

1. 使用 ansible-vaultencrypt 进行加密文件

[root@manager task]# ansible-vault-2 encrypt task_error_4.yml 
New Vault password: 
Confirm New Vault password: 
Encryption successful
#加密后的结果
[root@manager task]# cat task_error_4.yml 
$ANSIBLE_VAULT;1.1;AES256
64316530323535383362666364323130396438346539363735303437303662656638333239643336
3838666136323138306333643963343639623735333136630a663037616638666537386339363265
62313065646336336461373830356566643932613035393234663463313930653565633464643935
3661663566373763330a643338333232383638643732366236623865383366383734623666373536
61386337333966356635623130663033653264303234636264316535383730303132626131653461
30343636343530323435613631373233663338336538356134353436366663353430336137336535
31386131373533333833373265613361316630396535653836343239636631666634356265666463
66613837303733623166323930353162366364663330326361363934393839366533366439346536
33366635343331303232643963353962666533363066306436636465643139633135643337393239
61356662653365366665346139326664353264336164633139343638656465366665376634663262
66653433646137336337313862616530616330336532656434343136636539353333343037613266
64316338633762376533383730316239336532396131303864323734313638323764656366653164
65393731353862356664646463373932653734333039356130383633353330333035306662313532
39346261386135333766366336626530323865346535613239653135656131343633343661366361
30303236306335383533356137323564373731623364633138306234373465656538393736383038
64336339313965363961613436643330643963373861666130623737656166396332383833326335
37383462303261363430623931356435333339623366316264646330353865333062653830386366
32323439313438303137663332316663383531356336376561656362653261613161326239636235
62626362643439313536313764376361656535343262383464306534613764356638303431316239
37346661663466663565623332383466323039343232346666306666366663306534383666653163
31613436613332653366626564373361336237636431356434306233656266646461316266316663
31616263653531653765613938643532653833623030373336633661383732613636316163363938
37626161326563626261636538643231383866303563386634646164336661636663376561633430
35323864663033346134633162326266623832306666353364313034396663373630616139663663
32333036666266646137333735396434633932323163313964633132396334323166303561656366
66303136343836646330323838353864373637653235303963376332356339326266646463623731
35656661333430633439646131326334326532643035656166343264313134343633643035623632
61363366323234363765636431373263626530646339653435373033313237373133396533633234
32323739366538393364326463376137316663623435643131343366306563363939646462656634
34373561363330343663336466313565313234623463623262653664613736353263323366323633
32326265306165356162366632653431353331643330613537663661646333616565316636353734
30326431643661306262346237396332656135366564366537623361333166393232646363356632
36616365396432626265663635633732393837613661356161633236316266313462386136613437
36666332626665393134646462663235393465393038626338303936323731613665306535393832
65333863313531303962343536306333343934313433616431316139323235663138303234666232
32626235623433636334

2. 使用 --ask-vault-pass 参数执行加密的文件

[root@manager task]# ansible-playbook task_error_4.yml --ask-vault-pass
Vault password:

3. 使用 ansible-vault view 查看加密的文件

[root@manager task]# ansible-vault view task_error_4.yml 
Vault password:   #输入密码

4. 使用 ansible-vault edit 编辑加密的文件

[root@manager task]# ansible-vault edit task_error_4.yml 
Vault password:   #输入密码

5. 使用 ansible-vault rekey 改变加密的文件

[root@manager task]# ansible-vault rekey task_error_4.yml 
Vault password: #旧密码
New Vault password:  #新密码

6. 使用密码文件执行加密的 playbook

[root@manager task]# echo "talent" > file_pass
[root@manager task]# chmod 600 file_pass 
[root@manager task]# ll file_pass 
-rw------- 1 root root 7 Oct 30 16:52 file_pass
[root@manager task]# ansible-playbook task_error_4.yml --vault-password-file=file_pass
# 在 ansible.cfg 里新增 vault_password_file 参数,并指定密码文件路径。
[root@manager task]# vim ansible.cfg
[defaults]
vault_password_file = file_pass

7. 使用 ansible-vault 移除加密文件

[root@manager task]# ansible-vault decrypt task_error_4.yml 
Vault password: 
Decryption successful
此文章已被阅读次数:正在加载...更新于

请我喝[茶]~( ̄▽ ̄)~*

Xu Yong 微信支付

微信支付

Xu Yong 支付宝

支付宝