Ansible流程

Ansible流程
[TOC]
when判断
- 假设服务器主机名为
web01.example.com
| 表达式 | 含义 | 结果 |
|---|---|---|
| 等于 (==) | 完全一样才算匹配 | ❌️不匹配 (因为 web01.example.com 不等于 web01) |
| is match | 开头必须和你写的完全一样 | ✅️匹配 (因为 web01.example.com 确实是以 web01 开头的) |
| is search | 主机名里面包含你写的这部分就行 | ✅️匹配 (因为 web01.example.com 里确实包含了 web01) |
==(等于): 最严格!要求主机名一模一样,一字不差
- 用得少,因为实际主机名可能更复杂
is match: 比较严格,看开头
- 你想让所有以
web开头的服务器执行任务
- 比如
web01,web02,web-db-backupis search: 最宽松!适合==模糊查找==
- 你想让所有主机名里含有
web的服务器执行任务- 比如
web01,backup-web-data,web-db-server都会匹配
1)主机名称为web01安装wget命令# 这里使用的是==必须完全等于才行![root@m01 ansible]# vim when.yml- hosts: webs tasks: - name: Install wget yum: name: wget state: present when: ansible_hostname == "web01" # 这个when模块和上面的yum模块对齐! # 这里内置变量不需要加"{{ }}" # 后面web01必须加上双引号" "[root@m01 ansible]# ansible-playbook --syntax-check when.yml[root@m01 ansible]# ansible-playbook when.ymlskipping: [web02]ok: [web01]'跳过web02,只在web01上执行'
2)web01下载wget web02下载tree命令[root@m01 ansible]# vim when.yml- hosts: webs tasks: - name: Install wget yum: name: wget state: present when: ansible_hostname == "web01"
- name: Install tree yum: name: tree state: present when: ansible_hostname == "web02"[root@m01 ansible]# ansible-playbook when.ymlTASK [Install wget]*****skipping: [web02]ok: [web01] # 跳过web02TASK [Install tree] *****skipping: [web01]ok: [web02] # 跳过web01
3)并且关系# 同时满足才行[root@m01 ansible]# vim when.yml- hosts: webs tasks: - name: Install wget yum: name: wget state: present when: (ansible_hostname == "web01") and (ansible_default_ipv4.address == "10.0.0.7" )# 这个是and连接,两边用小括号连接起来!'或者使用列表的方式' when: - ansible_hostname == "web01" - ansible_default_ipv4.address == "10.0.0.7"# 并且关系,更加的清楚
4)或者关系 orwhen: (ansible_hostname == "web01") or (ansible_default_ipv4.address == "10.0.0.8")[root@m01 ansible]# ansible-playbook when.ymlok: [web01]ok: [web02]Nginx判断实战
1️⃣阶段一

- hosts: webs tasks: - name: Configure nginx repo yum_repository: name: nginx-stable description: nginx stable repo baseurl: https://nginx.org/packages/centos/7/$basearch/ gpgcheck: no enabled: yes
- name: Install nginx server yum: name: nginx state: present
- name: Configure copy nginx file copy: src: ./nginx.conf dest: /etc/nginx/
- name: Create group www group: name: www gid: 888
- name: Create user www user: name: www uid: 888 group: www shell: /sbin/nologin create_home: false
- name: Start nginx server systemd: name: nginx state: started enabled: yes
- 重新执行一遍都是绿色的,说明没有任何的改变!!
[root@m01 ~]# vim nginx.confuser nginx;# 启动用户由www-->nginx- 我们改动一下配置文件!
- 再执行一遍会怎样❓️

- 我们来看一下它的启动用户是谁??
[root@web01 ~]#ps aux | grep nginxwww S 08:24 0:00 nginx: worker process'依旧是www用户!'2️⃣阶段二

Handler 是什么?
你可以把 Handler 想象成一个待命的“服务兵”
- 普通任务 (Task): 像勤劳的工人,Playbook 一运行,它们就立刻干活
- Handler: 像是等待指令的特警队员,站在一旁待命
- 只有收到特定的“信号”,它才会行动
-
触发 (Notify): 在一个普通的 Task 里,比如“拷贝 nginx 配置文件”
-
你加上一个
notify: restart nginx -
这个
notify就是“信号”或“通知”
-
判断与执行: Ansible 执行*“拷贝 nginx 配置文件”*这个任务时
-
它会特别留意:这次操作有没有改变什么东西?
-
如果没有改变:
- 比如本地的配置文件和服务器上的文件一模一样
- 那么,
notify就像没听到一样,handler 不会被触发,服务不会重启
-
如果有改变:
- 比如本地的配置文件发生了改变,拷贝操作成功更新了服务器上的文件
- 这时,Ansible 认为这个任务“状态改变了”
- 它就会立刻向*“重启 nginx”*这个 handler 发送一个==“信号”==
- 💡 注意:此时还没重启!只是“记住了要重启”
统一执行: 所有的 Tasks 都跑完后,在 Playbook 的最后阶段
-
Ansible 会检查有哪些 handler 收到了信号
-
它会把所有收到信号的 handlers 都按顺序执行一遍
- 🎯 重点:即使同一个 handler 被多个 task 触发了
- 也只会执行一次
- 🎯 重点:即使同一个 handler 被多个 task 触发了
-
如果没人通知它,它就一直待命,啥也不干
🌟为什么要这么设计? (好处)
- 避免不必要的操作:
- 盲目重启,不仅浪费资源,还可能导致短暂的服务中断
- Handler 保证了只有在真正需要(配置变了)的时候才重启
- 提高效率:
- 即使你的 playbook 里有 10 个地方都修改了 nginx 配置
- 并且都想重启 nginx
- 使用
notify也能确保 nginx 最终只被重启一次,而不是 10 次
- hosts: webs tasks: - name: Install nginx server yum: name: nginx state: present
- name: Configure copy nginx file copy: src: ./nginx.conf dest: /etc/nginx/ notify: Restart nginx # 只要有改变,就给名字为Res..的handler发信号 # 和copy平级
- name: Start nginx server systemd: name: nginx state: started enabled: yes
handlers: # 跟tasks平级,前面没有- - name: Restart nginx # 这个name和上面的notify保持一致 # 最后,不管收到几次信号,只重启一次 systemd: name: nginx state: restarted- 上面的配置文件少了yum仓库配置, 创建组和用户!
现在webs的运行用户还是www'www nginx: worker process'我们给配置文件首行加一个空行!# 也算是配置文件发生了改变
[root@web01 ~]#ps aux | grep nginxnginx nginx: worker process'现在启动用户就是nginx了!'但如果我的配置文件改错了!那么它重启也会报错的❌️[root@m01 ~]# head -1 nginx.confser nginx;# 少一个u[root@m01 ~]# ansible-playbook nginx.ymlTASK [Configure copy nginx file]changed: [web01]changed: [web02]'配置文件依旧改变!'....RUNNING HANDLER [Restart nginx]fatal: [web02]: FAILED! => {"changed": false, "msg": "Unable to restart service nginx:"# 重启部分直接报错了!!'webs的nginx也停止'[root@web01 ~]#ps aux | grep nginx|grep -v grep | wc -l03️⃣阶段三

- hosts: webs gather_facts: no tasks: - name: Configure copy nginx file copy: src: ./nginx.conf dest: /etc/nginx/ notify: Restart nginx # 只要有改变,就给名字为Res..的handler发信号 # 和copy平级
- name: Check nginx from ng_re command: "nginx -t" register: ng_re # 把这条命令的结果返回给变量ng_re ignore_errors: yes # 当结果错误时候忽略掉、继续向下执行
handlers: # 跟tasks平级,前面没有- - name: Restart nginx # 这个name和上面的notify保持一致 # 最后,不管收到几次信号,只重启一次 systemd: name: nginx state: restarted when: ng_re.stderr_lines is search "successful" # 当返回的变量找到了successful # 且收到了notify的信号(配置文件修改)才能重启=============================== when: ng_re.rc is match "0" # 我们也可以通过状态码是否为0来判断是否执行成功 # 上面是匹配以0开头的... 这个 == 0 不成立! # 后面还有个逗号, "rc": 0,- 下面是
nginx -t正常的返回结果- 用debug模块中的 msg
- name: Print nginx_result debug: msg: "{{nginx_re}}"=============================== "msg": { "changed": true, "cmd": [ "nginx", "-t" ], "delta": "0:00:00.004444", "end": "2026-04-04 15:04:48.508624", "failed": false, "msg": "", ✅️"rc": 0, "start": "2026-04-04 15:04:48.504180", "stderr": "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok\nnginx: configuration file /etc/nginx/nginx.conf test is successful", ✅️"stderr_lines": [ "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok", "nginx: configuration file /etc/nginx/nginx.conf test is successful" ], "stdout": "", "stdout_lines": [] }}1)我们再次修改配置文件,触发notify[root@m01 ~]# vim nginx.confuser nginx;# 改正确![root@m01 ~]# ansible-playbook nginx.ymlweb01 : ok=3 changed=3web02 : ok=3 changed=3# 三步都改变!2)notify给handler发信号,我的配置文件修改了!请重启# 是否真的重启,还要看when判断!3)第二步nginx -t执行成功了-->变量里面有successful4)handler收到信号,是否重启由when判断5)when从变量中找到了successful,且handler收到了信号6)重启Nginx===============================# 那我们试着把配置文件改错试试会怎么样!![root@m01 ~]# vim nginx.confser nginx;[root@m01 ~]# ansible-playbook nginx.yml
'ignore_errors: yes'# 当nginx -t执行失败,则不中断,继续往下走!===============================如果没有忽略,则直接中断!# 跳出playbook,不往下执行了
- ==最终版==
- hosts: webs tasks: - name: Configure nginx repo yum_repository: name: nginx-stable description: nginx stable repo baseurl: https://nginx.org/packages/centos/7/$basearch/ gpgcheck: no enabled: yes
- name: Install nginx server yum: name: nginx state: present
- name: Create Group www group: name: www gid: 666 state: present
- name: Create User www user: name: www uid: 666 group: www shell: /sbin/nologin create_home: false
- name: Configure Nginx Server copy: src: nginx.conf dest: /etc/nginx/ notify: Restart Nginx Server
- name: nginx -t command: nginx -t register: ng_re ignore_errors: yes
- name: Start Nginx Server # 开机启动&&自启 systemd: name: nginx state: started enabled: yes
handlers: - name: Restart Nginx Server # 配置文件修改重启 systemd: name: nginx state: restarted enabled: yes when: ng_re.rc is match "0"字典循环
[root@m01 ansible]# vim f.yml- hosts: web01 tasks: - name: Create many file file: path: - a.txt - b.txt state: touch[root@m01 ansible]# ansible-playbook --syntax-check f.ymlplaybook: f.yml[root@m01 ansible]# ansible-playbook f.ymlchanged: [web01]# 也是执行成功了![root@web01 ~]#ls'['\''a.txt'\'', '\''b.txt'\'']'# ❌️回到web01进行验证,这是创建了个啥!⚠️file不支持这样创建文件[root@web01 ~]#rm -rf ./*[root@web01 ~]#ls | wc -l0# 都删除了
1)创建多个文件[root@m01 ansible]# vim f.yml- hosts: web01 tasks: - name: Create many file file: path: "{{item}}" # 固定用法,必须是item state: touch loop: # 和file对齐,loop就是循环的意思! - a.txt - b.txt[root@web01 ~]#lsa.txt b.txt[root@web01 ~]#ls | wc -l2# 成功创建出来两个文件'权限不同,属主不同'[root@m01 ansible]# cat f.yml- hosts: web01 tasks: - name: Create many files file: path: "{{item.path}}" state: touch owner: "{{item.owner}}" group: "{{item.group}}" mode: "{{item.mode}}" loop: - {path: a.txt, owner: root, group: root, mode: "0644"} - {path: b.txt, owner: www, group: www, mode: "0755"} # 这个权限(是数字)必须要加引号 # 用大括号括起来[root@m01 ansible]# ansible-playbook --syntax-check f.ymlplaybook: f.yml[root@m01 ansible]# ansible-playbook f.ymlchanged: [web01] => (item={'path': 'a.txt', 'owner': 'root', 'group': 'root', 'mode': '0644'})changed: [web01] => (item={'path': 'b.txt', 'owner': 'www', 'group': 'www', 'mode': '0755'})[root@web01 ~]#ls -lhtotal 0-rw-r--r-- 1 root root 0 Apr 5 20:55 a.txt-rwxr-xr-x 1 www www 0 Apr 5 20:55 b.txt
2)拷贝多个文件[root@m01 ansible]# vim c.yml- hosts: web01 tasks: - name: Copy many files copy: src: "{{item.src}}" dest: "{{item.dest}}" mode: "{{item.mode}}" loop: # 使用下面这种方法也是可以的,更加清晰! - src: rsyncd.conf dest: /home/ mode: "0600" - src: info.txt dest: /home/ mode: "0644"[root@m01 ansible]# ansible-playbook --syntax-check c.ymlplaybook: c.yml[root@m01 ansible]# ansible-playbook c.ymlchanged: [web01] => (item={'src': 'rsyncd.conf', 'dest': '/home/', 'mode': '0600'})changed: [web01] => (item={'src': 'info.txt', 'dest': '/home/', 'mode': '0644'})[root@web01 ~]#ls -lh /home/-rw-r--r-- 1 root root 106 Apr 5 21:16 info.txt-rw------- 1 root root 427 Apr 5 21:16 rsyncd.conf
3)创建多个组和用户[root@m01 ansible]# vim g.yml- hosts: web01 tasks: - name: Create many groups group: name: "{{item.name}}" gid: "{{item.gid}}" loop: - name: test01 gid: "778" - name: test02 gid: "779" # 这些数字前面一定要加引号!
- name: Create many users user: name: "{{item.name}}" uid: "{{item.uid}}" group: "{{item.group}}" shell: "{{item.shell}}" create_home: "{{item.home}}" # 后面这个点后面的东西随便写! # 只要能够与下面的loop对应就可以 loop: - name: test01 uid: "778" group: test01 shell: /sbin/nologin home: false # 这个home与上面的item.home相对应! - name: test02 uid: "779" group: test02 shell: /bin/bash home: true[root@m01 ansible]# ansible-playbook --syntax-check g.yml[root@m01 ansible]# ansible-playbook g.yml'测试验证部分'[root@web01 ~]#id test01uid=778(test01) gid=778(test01) groups=778(test01)[root@web01 ~]#id test02uid=779(test02) gid=779(test02) groups=779(test02)[root@web01 ~]#grep test /etc/passwdtest01❌778:778::/home/test01:/sbin/nologintest02❌779:779::/home/test02:/bin/bash[root@web01 ~]#ls -d /home/test02//home/test02/
4)同时重启NGINX和PHP服务[root@m01 ansible]# vim re.yml- hosts: web01 tasks: - name: Restart server systemd: name: "{{item}}" state: restarted loop: - nginx - php-fpm[root@m01 ansible]# ansible-playbook re.ymlchanged: [web01] => (item=nginx)changed: [web01] => (item=php-fpm)Jinja2模版
Jinja2 模板文件(.j2)里有两个“逻辑控制”
- ==for循环== 和 ==if判断==
你就把 .j2 文件想象成一个**“填空题试卷”**:
{{ }}是用来填答案的(变量)template模块的用法,参考 ==📚Ansible03==- 对比着
copy模块
- 对比着
{% %}是用来写“解题指令”的(循环和判断)
在 Ansible 里,循环主要出现在两个地方,我们一个个来看:
🛠️ 场景一:在 ==任务playbook== 里循环(干活时用)
- 这是最常用的, 比如你要创建 3 个用户
- 配合
loop关键字, 和{{ item }}变量- 就是我们上面👆的字典循环
📄 场景二:在 ==模板.j2== 里循环(生成文件时用)
-
当你需要生成配置文件,里面有一堆重复的段落
-
只是 IP或端口 不一样时,就用
{% for %}
| 特性 | 第一组:任务级循环 | 第二组:模板级逻辑 |
|---|---|---|
| 核心关键词 | loop 和 {{ item }} | {% for %} 和 {% if %} |
| 写在哪里? | Playbook (.yml 文件) | 模板 (.j2 文件) |
| 谁来配合? | 任何模块都能配 (如 yum, user) | 必须配合 template 模块使用 |
| 变量怎么传? | 直接用 loop 列表 | 靠 Playbook 里的 vars 传进去 |
For 循环:
{% for 变量名 in 列表数据 %} 这里写重复的内容,用 {{ 变量名 }} 来引用当前的数据{% endfor %}===============================1)列表数据我们经常用 range# range(7,9)--->包含7,不包含9# 7,82)模板里换行了,会出现空白'可以加减号 - '减号 - 贴着哪边,就吸掉哪边的“空白”(换行符或空格)⚠️这个 - 写在里面{%- for n in range(7,9) %}{%- endfor %}# 把前面的空白都吸走!===============================🦄案例: 生成负载均衡的配置文件[root@m01 ansible]# vim lb.conf.j2upstream {{server_name}} {{%- for n in range(7,9) %} server 172.16.1.{{n}}:{{ up_port }}{%- endfor %}}server { listen 80; server_name {{ server_name }};
location / { root /code; index index.html; proxy_pass http://{{ server_name }}; proxy_set_header Host $http_host; }}# 里面总共两个变量--->在剧本中定义vars变量[root@m01 ansible]# vim l.yml- hosts: web01 vars: - server_name: wp.kpyun.com - up_port: 80 # 先写vars变量,后写task任务 # tasks和vars对齐 tasks: - name: Configure lb file template: src: ./lb.conf.j2 dest: /etc/nginx/conf.d/lb.conf
'测试验证!'[root@web01 ~]#cat /etc/nginx/conf.d/lb.confupstream wp.kpyun.com { server 172.16.1.7:80 server 172.16.1.8:80} # 最后的大括号在这!server { listen 80; server_name wp.kpyun.com;...If 判断
'基本语法结构:'{% if 条件成立 %} 写这段内容{% elif 其他条件 %} 写那段内容{% else %} 如果上面都不对,就写这个{% endif %}===============================🦄案例.将keepalived.conf.j2拷贝到两台webrouteid--->都以自身主机名称生成# web01生成是角色master 票数150# web02生成的角色backup 票数100===============================[root@m01 ansible]# vim keepalived.conf.j2global_defs { router_id {{ ansible_hostname }}}
vrrp_instance VI_1 {{% if ansible_hostname is match "web01" %} # 实际这里面应该是lb01 state MASTER priority 150{% else %}# 这里用elif再进行判断也是可以的! state BACKUP priority 100{% endif %}
interface eth0 virtual_router_id 50 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 10.0.0.3 }}# .j2模版文件只有if判断[root@m01 ansible]# vim k.yml- hosts: webs tasks: - name: Configure keepalived file template: src: ./keepalived.conf.j2 dest: /root/keepalived.conf[root@m01 ansible]# ansible-playbook k.ymlchanged: [web02]changed: [web01]# 两台web都改变了,我们细看配置文件
'测试验证'[root@web01 ~]# cat keepalived.confglobal_defs { router_id web01}# 主,优先级150vrrp_instance VI_1 { state MASTER priority 150 .....[root@web02 ~]# cat keepalived.confglobal_defs { router_id web02}# 是备份,优先级100vrrp_instance VI_1 { state BACKUP priority 100 ......📚任务标签
# 默认情况:当你运行一个playbook(一堆任务的集合),Ansible就像一个忠实的机器人,会老老实实地把所有的任务都执行一遍Ansible的标签(tag)功能可以给单独任务或者一部分任务打上标签然后利用这些标签:-t 🏷️ # 只做带标签的事,其他都跳过--skip-tags 🏷️ # 跳过特定标签任务,除了它都运行--list-tags # 查看有哪些标签=========================================[root@m01 ansible]# vim t.yml- hosts: web01 tasks: - name: Configure nginx file copy: src: ./nginx.conf dest: /etc/ tags: conf # 别忘记加s # 标签名随便起
- name: nginx -t command: "nginx -t" ignore_errors: yes tags: nt
- name: Restart nginx systemd: name: nginx state: restarted[root@m01 ansible]# ansible-playbook --syntax-check t.ymlplaybook: t.yml[root@m01 ansible]# ansible-playbook t.yml'先正常执行一遍!'TASK [Configure nginx file]changed: [web01]*****************TASK [nginx -t]changed: [web01]*****************TASK [Restart nginx]changed: [web01]# 三个都执行了一遍!=========================================1)查看有哪些标签🏷️[root@m01 ansible]# ansible-playbook t.yml --list-tags play #1 (web01): web01 TAGS: [] TASK TAGS: [conf, nt]'两个标签 conf和nt '
2)运行特定标签[root@m01 ansible]# ansible-playbook t.yml -t nt# 后接标签名TASK [nginx -t]changed: [web01]'只运行了这个nt标签'
3)跳过标签# 后面也必须跟标签名!🏷️[root@m01 ansible]# ansible-playbook t.yml --skip-tags confTASK [nginx -t]changed: [web01]*******************TASK [Restart nginx]changed: [web01]"跳过了配置这一步,只运行了-t检测和重启"# 我们试着后面可不可以跟多个标签!❌️--skip-tags conf nt # 不能用空格隔开✅️--skip-tags conf,nt # 可以用逗号隔开[root@m01 ansible]# ansible-playbook t.yml --skip-tags conf,ntTASK [Restart nginx]changed: [web01]'这样的话只执行了重启的任务'🦄# 但其实有更简便的方法🦄1)可以给多个不同的任务打上相同的标签2)这样用 --skip-tags 一次性跳过所有这些打了相同标签的任务- hosts: web01 tasks: - name: Configure nginx file copy: src: ./nginx.conf dest: /etc/nginx/ tags: test
- name: nginx -t command: "nginx -t" ignore_errors: yes tags: test
- name: Restart nginx systemd: name: nginx state: restarted# 都打上了test标签🏷️[root@m01 ansible]# ansible-playbook t.yml --list-tags play #1 (web01): web01 TAGS: [] TASK TAGS: [test][root@m01 ansible]# ansible-playbook t.yml --skip-tags testTASK [Restart nginx]changed: [web01]# 同样只运行了Restart操作📚文件复用
以前写多个playbook没有办法,一键执行# 需要按照顺序一个个去做,这很麻烦1)现在可以把你常用的一些任务(比如安装Nginx、配置php)写在不同的文件里# 让每个部分更清晰、更易于维护和复用2)最后写一个主任务清单(main playbook),把它们包含在里面3)我们只需要执行主任务清单,它会运行被包含进来的任务# 从而实现真正的“一键部署”=========================================需求: web01配置并重启Nginx, web02配置并重启php
1)准备两个tasks文件[root@m01 ansible]# vim n.yml'直接从- name开始写'# 被包含在all.yml中- name: Copy Nginx server copy: src: ./nginx.conf dest: /etc/nginx/
- name: nginx -t command: "nginx -t" ignore_errors: yes
- name: Restart nginx server systemd: name: nginx state: restarted
[root@m01 ansible]# vim p.yml- name: Copy php configure copy: src: ./www.conf dest: /etc/php-fpm.d/
- name: Restart php systemd: name: php-fpm state: restarted
2)编写主任务清单# 将上面两个文件包含引入[root@m01 ansible]# vim all.yml- hosts: webs tasks: - name: Nginx part # 名字随便起 include_tasks: n.yml when: ansible_hostname is match "web01" # 只有匹配到web01时执行nginx..
- name: php part include_tasks: p.yml when: ansible_hostname is match "web02" # 只有匹配到web02时执行php..
3)检测&&执行[root@m01 ansible]# ansible-playbook --syntax-check n.yml# 检测的时候,不能单独检测n.yml和p.yml,它们俩是子文件'肯定有问题呀!'--->它们是以 - name开头❌️✅️应该直接检测all.yml文件[root@m01 ansible]# ansible-playbook --syntax-check all.ymlplaybook: all.yml[root@m01 ansible]# ansible-playbook all.ymlPLAY [webs]********************TASK [Nginx part] --->"主任务清单"skipping: [web02]included: /home/ansible/n.yml for web01'跳过web02,只执行web01'********************TASK [Copy Nginx server]ok: [web01]********************TASK [nginx -t]changed: [web01]********************TASK [Restart nginx server]changed: [web01]'web01依次执行以上三步!'********************TASK [php part] --->"主任务清单"skipping: [web01]included: /home/ansible/p.yml for web02'跳过web01'********************TASK [Copy php configure]ok: [web02]********************TASK [Restart php]changed: [web02]'web02执行php部分'********************web01 : ok=4 changed=2web02 : ok=3 changed=1⚠️主任务清单只有两个任务⚠️抑制changed
在 Ansible 中,一个任务执行后,根据它是否真的改变了目标主机的状态,会在输出中显示不同的颜色:
- 绿色 (OK): 表示任务执行了,但目标主机的状态没有发生改变。
- 黄色 (Changed): 表示任务执行了,并且确实对目标主机做了修改
command 模块执行任何命令,默认情况下都会被认为是 changed 状态(黄色)
- 即使
nginx -t只是测试配置,它确实是在目标主机上执行了一个操作- 所以 Ansible 会认为这是一个“变化”(Changed)
changed_when: false
- 来强制覆盖其默认的
changed状态,使其显示为ok(绿色)- 从而让整个 playbook 的执行结果更具可读性和准确性
像
df -h、ls、ps aux、free -m、cat /etc/hostname它们的主要目的都是查询、查看或诊断系统状态,而不是去修改任何东西
可以让这些执行了操作但未改变系统状态的任务,能正确地显示为绿色 (OK)
[root@m01 ansible]# vim c.yml- hosts: web01 tasks: - name: nginx -t command: "nginx -t" register: ng_re ignore_errors: yes tags: check# 没有抑制前[root@m01 ansible]# ansible-playbook c.ymlTASK [nginx -t]changed: [web01]'每运行一次都会执行一遍!'- hosts: web01 tasks: - name: nginx -t command: "nginx -t" register: ng_re ignore_errors: yes tags: check changed_when: false[root@m01 ansible]# ansible-playbook c.ymlTASK [nginx -t]ok: [web01]'现在运行都是OK✅️'# 由changed(黄色)-->ok(绿色)文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!



