# 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 |
