Ansible Playbook 进阶探秘:Handlers、变量、循环及条件判断全解析
| 192.168.60.100 | ansible.com |
| 192.168.60.110 | client-1.com |
| 192.168.60.120 | client-2.com |
| 192.168.60.130 | client-1.com |
一、Handlers
介绍:在发生改变时执行的操作(类似puppet通知机制)
示例:
当apache的配置文件发生改变时,apache服务才会重启。
- hosts: webservers
remote_user: root
tasks:
- name: apache
yum: name=httpd state=present
- name: apache config
copy: src=/config/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- start httpdhandlers:
- name: start httpd
service: name=httpd state=restarted

测试:
配置文件没有改变——

(可以看到没有重启服务的任务)
修改apache的配置——
[root@ansible playbook]# vim /config/httpd.conf #修改端口
Listen 8080
(当配置发生修改后,可以看到重启服务的任务已经被执行)
二、变量的使用
常用的变量一般就两种:
- 一种为用户自己定义的变量
- 一种为facts获取的变量(即ansible webserver -m setup查到的变量)
1.自定义变量
(1)用户在.yaml文件自定义变量
示例:
[root@ansible playbook]# vim test1.yaml
- hosts: webservers
remote_user: root
vars:
- var1: "abc"
- var2: 123
tasks:
- name: test vars
shell: echo "{{ var1 }} {{ var2 }}" >> /tmp/var.txt

测试:

(定义的变量成功写入到被管控端主机的var.txt文件)
(2)通过-e参数传递变量
示例:
[root@ansible playbook]# vim test2.yaml
- hosts: webservers
remote_user: root
tasks:
- name: install package
yum: name={{ packname }} state=present

测试:
(使用-e传递参数安装namp)
(3)通过主机/主机组配置文件传递变量
主机——
示例:
[root@ansible playbook]# vim /etc/ansible/hosts
192.168.60.110 packname=nmap

[root@ansible playbook]# vim test3.yaml
- hosts: 192.168.60.110
remote_user: root
tasks:
- name: install package
yum: name={{ packname }} state=present
测试:

(参数成功传递)
主机组——
示例:
[root@ansible playbook]# vim /etc/ansible/hosts
[webservers]
192.168.60.110
192.168.60.120
192.168.60.130
[webservers:vars]
packname=nmap

[root@ansible playbook]# vim test4.yaml

测试:

(参数传递成功)
2.通过facts获取的系统的变量
(1)获取系统变量
即ansible webserver -m setup查到的变量
使用方法:
[root@ansible playbook]# ansible webservers -m setup > /tmp/fact.txt
[root@ansible playbook]# vim /tmp/fact.txt


在剧本中直接调用这些变量名就行,但是注意这些变量名是分级别的,对齐的就是同一级,比如ansible_default_ipv4和ansible_nodename就是同一级,address是ansible_default_ipv4的 下一级,要调用它就需要在ansible_default_ipv4后面加上一个“.”,就是写成这样ansible_default_ipv4.address。
(其实就是字典,以键值对的方式关联起来,这里说变量是为了帮助理解)
示例:
[root@ansible playbook]# vim facts.yaml #获取ip、主机名等系统变量信息
- hosts: webservers
remote_user: root
tasks:
- name: hostname ipaddrss
shell: echo "{{ ansible_default_ipv4.address }} {{ ansible_nodename }}" > /tmp/facts.txt
- name: fetch file /tmp/facts
fetch: src=/tmp/facts.txt dest=/tmp
测试:
[root@ansible playbook]# ansible-playbook facts.yaml


(2)本地facts(facts.d)自定义系统变量
解释:就是定义ansible webserver -m setup查到的变量
示例:
[root@client-1 ~]# mkdir -p /etc/ansible/facts.d #在被管控端创建如下目录
[root@client-1 ~]# touch /etc/ansible/facts.d/test.fact #创建文件
[root@client-1 ~]# vim /etc/ansible/facts.d/test.fact #写入要定义的变量名
[general]
test_test1=123
test_test2=abc
测试:
[root@ansible playbook]# ansible 192.168.60.110 -m setup | grep test_test
#获取自定义的系统变量

(获取成功!)
3.变量注册
介绍:在 Ansible 的 Playbook 里,变量注册是一项非常实用的功能。借助它,我们能够把某个命令的执行结果存储到变量中,方便后续使用。这一特性能够在很多场景下避免编写特定于站点的复杂逻辑。比如,你可以利用变量注册来检查系统中是否存在某个特定程序。具体操作时,只需使用 register 关键字指定用于存储结果的变量即可。通过这种方式,你可以在后续任务中根据存储的结果进行条件判断和进一步操作。
示例:
[root@ansible playbook]# vim test5.yaml
- hosts: webservers
remote_user: root
tasks:
- name: get user info
shell: grep ^root /etc/passwd
register: pass_content
- name: save info
shell: echo {{ pass_content }} > /tmp/user.txt

(获取root用户信息存进pass_content里面)
测试:


(可以看到存入客户端/tmp/user.txt文件下的信息是以键值对的形式,我们可以用来调用这些键值对,这个需要和后面要学的判断结合起来使用,单独看确实没什么用,下面是如何调用)
[root@ansible playbook]# vim test5.yaml #调用
- hosts: webservers
remote_user: root
tasks:
- name: get user info
shell: grep ^root /etc/passwd
register: pass_content
- name: save info
shell: echo {{ pass_content.stdout }} > /tmp/user1.txt

[root@ansible playbook]# ansible-playbook test5.yaml

[root@client-1 ~]# cat /tmp/user1.txt

三、剧本中的条件判断
ansible和puppet软件相同 是可以支持条件判断,使用when语句。
示例1
[root@ansible playbook]# vim test6.yaml
- hosts: webservers
remote_user: root
tasks:
- name: install tree
yum: name=tree state=present
when: ansible_nodename == "client-1.com"
- name: install nmap
yum: name=nmap state=present
when: ansible_nodename == "client-2.com"

(设置条件判断,当被管控端的主机名叫client-1.com时安装tree,叫client-2.com时安装nmap)
测试:

(可以看到条件判断将不符合条件的主机全部跳过去了)
示例2
条件判断+变量注册
[root@ansible playbook]# vim apache_test.yaml
- hosts: webservers
remote_user: root
tasks:
- name: get pkg info
shell: rpm -qa | grep httpd | awk -F'-' 'NR == 1 {print$1}'
register: pkginfo
- name: install httpd
yum: name=httpd state=present
when: pkginfo.stdout != "httpd"

测试:
[root@ansible playbook]# ansible-playbook apache_test.yaml

(由于我的三台被管控机都安装过了httpd,所以可以看到都跳过去了)
(紫色字体的警告不用管,没有影响,如果嫌烦可以按照下面的方式去掉)
[root@ansible playbook]# vim /etc/ansible/ansible.cfg
command_warnings=False


(这样执行就没有警告了)
示例3
源码部署nginx并启动服务
1.规划
基础功能:
- 本地部署,打包
- 需要判断目标主机是否已经安装nginx
扩展:
- 通过配置文件是否改动触发启动
2.准备本地源码包nginx
[root@ansible /]# wget https://nginx.org/download/nginx-1.27.4.tar.gz

(复制链接直接wget就行,这样就在本地下载下来了nginx的源码包)
[root@ansible /]# tar -xvf /nginx-1.27.4.tar.gz -C /usr/local/src/
[root@ansible /]# cd /usr/local/src/nginx-1.27.4/
[root@ansible nginx-1.27.4]# yum install gcc gcc-c++ pcre-devel zlib-devel
[root@ansible nginx-1.27.4]# useradd -m -s /sbin/nologin nginx
[root@ansible nginx-1.27.4]# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx
[root@ansible nginx-1.27.4]# make
[root@ansible nginx-1.27.4]# make install
[root@ansible local]# cd /usr/local
[root@ansible local]# tar -zcvf /playbook/nginx.tar.gz nginx/

3.编写剧本
[root@ansible playbook]# vim snginx_install.yaml
- hosts: webservers
remote_user: root
tasks:
- name: copy nginx
copy: src=/playbook/nginx.tar.gz dest=/tmp
- name: get nginx info
shell: ls -d /usr/local/nginx
register: nginx_info
ignore_errors: yes
- name: unzip nginx
shell: tar -xvf /tmp/nginx.tar.gz -C /usr/local
when: nginx_info.rc == 2
- name: add user
user: name=nginx state=present
- name: modify nginx
file: path=/usr/local/nginx owner=nginx group=nginx recurse=yes state=directory
剧本说明:
- hosts: webservers
remote_user: root
tasks:
- name: copy nginx #拷贝源码到到管控机
copy: src=/playbook/nginx.tar.gz dest=/tmp
- name: get nginx info #注册变量用于判断是否安装了nginx
shell: ls -d /usr/local/nginx
register: nginx_info
ignore_errors: yes #未安装过nginx会报错,这里用来跳过保存,继续执行剧本
- name: unzip nginx #解压安装nginx
shell: tar -xvf /tmp/nginx.tar.gz -C /usr/local
when: nginx_info.rc == 2 #判断是否安装过nginx
- name: add user #添加nginx用户
user: name=nginx state=present
- name: modify nginx #递归设置用户和所属组为nginx
file: path=/usr/local/nginx owner=nginx group=nginx recurse=yes state=directory

相关说明:
ignore_errors: yes #当某个任务执行时出现错误,ignore_errors模块等于yes时,不会让整个剧本执行中断,而是会忽略这个错误,继续执行后续的任务
nginx.rc == 2 #这个是register的返回值,当返回值等于2的时候表明/usr/local/nginx目录已经存在
recurse=yes #这个是递归的修改权限
测试:
[root@ansible playbook]# ansible-playbook snginx_install.yaml


(可以看到注册变量任务的报错,因为没有安装过nginx,但是因为添加了ignore_errors模块,成功跳过了错误,继续执行剧本后面剩下的任务)



(被管控端的所有主机安装成功)


(这时候再执行就可以看到,注册变量模块没有再报错,因为所有节点都已经安装了nginx,而且解压nginx的任务判断成功也生效,安装过nginx的被管控机没有再次执行解压nginx的任务,这就节约了在实际运维场景下的时间)
4.扩展
[root@ansible playbook]# vim snginx_install.yaml
- hosts: webservers
remote_user: root
tasks:
- name: copy nginx
copy: src=/playbook/nginx.tar.gz dest=/tmp
- name: get nginx info
shell: ls -d /usr/local/nginx
register: nginx_info
ignore_errors: yes
- name: unzip nginx
shell: tar -xvf /tmp/nginx.tar.gz -C /usr/local
when: nginx_info.rc == 2
- name: add user
user: name=nginx state=present
- name: modify nginx
file: path=/usr/local/nginx owner=nginx group=nginx recurse=yes state=directory
- name: nginx config
copy: src=/playbook/nginx.conf dest=/usr/local/nginx/conf
notify:
- restart nginxhandlers:
- name: restart nginx
shell: /usr/local/nginx/sbin/nginx -s reload

测试:
启动管控端的nginx服务——
[root@client-1 ~]# /usr/local/nginx/sbin/nginx
[root@client-2 ~]# /usr/local/nginx/sbin/nginx
[root@client-3 ~]# /usr/local/nginx/sbin/nginx
配置文件nginx.conf没有修改——
[root@ansible playbook]# ansible-playbook snginx_install.yaml

(因为配置没有修改,所以nginx服务不会被重启,这样节约了时间)
修改nginx.conf的配置,将nginx的端口设置为8080——
[root@ansible playbook]# vim nginx.conf
listen 8080;

[root@ansible playbook]# ansible-playbook snginx_install.yaml

(配置文件发生改动,管控端重启被管控端所有主机的nginx服务)
四、剧本中的循环
剧本的循环是使用with_items关键字实现的。
(这个功能使用很少,判断功能用到的比较多)
示例1
添加abc1-abc3用户
[root@ansible playbook]# vim cycle.yaml
- hosts: webservers
remote_user: root
tasks:
- name: add user
user: name={{ item }} state=present
with_items:
- abc1
- abc2
- abc3
测试:
[root@ansible playbook]# ansible-playbook cycle.yaml



(用户再被管控端创建成功!)
示例2
依次安装软件 nmap wget tree
[root@ansible playbook]# vim cycle-1.yaml
- hosts: webservers
remote_user: root
tasks:
- name: pack install
user: name={{ item }} state=present
with_items:
- tree
- namp
- vsftpd
测试:
(软件安装成功!)
ansible自动化运维工具的介绍-CSDN博客
深度剖析 ansible:从部署基础到模块运用及剧本编写-CSDN博客
Ansible 实战:Roles,运维的 “魔法函数”-CSDN博客
相关文章:
Ansible Playbook 进阶探秘:Handlers、变量、循环及条件判断全解析
192.168.60.100ansible.com192.168.60.110 client-1.com 192.168.60.120client-2.com192.168.60.130client-1.com 一、Handlers 介绍:在发生改变时执行的操作(类似puppet通知机制) 示例: 当apache的配置文件发生改变时,apache服务才会重启…...
大模型ui设计SVG输出
你是一位资深 SVG 绘画设计师,现需根据以下产品需求创建SVG方案: 产品需求 约拍app 画板尺寸: 宽度:375px(基于提供的HTML移动设计)高度:812px(iPhone X/XS 尺寸) 配…...
40--华为IPSec VPN实战指南:构建企业级加密通道
🛡️ 华为IPSec VPN实战指南:构建企业级加密通道 “当数据开始穿盔甲,黑客只能望’密’兴叹” —— 本文将手把手教你用华为设备搭建军用级加密隧道,从零开始构建网络长城! 文章目录 🛡️ 华为IPSec VPN实战…...
基于分布式指纹引擎的矩阵运营技术实践:突破平台风控的工程化解决方案
一、矩阵运营的技术痛点与市场现状 风控机制升级 主流平台通过复合指纹识别(Canvas渲染哈希WebGL元数据AudioContext频率分析)检测多账号关联传统方案成本:单个亚马逊店铺因关联封号月均损失$5000,矩阵规模越大风险指数级增长 …...
MATLAB的24脉波整流器Simulink仿真与故障诊断
本博客来源于CSDN机器鱼,未同意任何人转载。 更多内容,欢迎点击本专栏目录,查看更多内容。 目录 0 引言 1 故障数据采集 2 故障特征提取 3 故障诊断分类 4 结语 本博客内容是在MATLAB2023下完成。 0 引言 对于电力电子电路的故障诊断…...
linux第三次作业
1、将你的虚拟机的网卡模式设置为nat模式,给虚拟机网卡配置三个主机位分别为100、200、168的ip地址 2、测试你的虚拟机是否能够ping通网关和dns,如果不能请修改网关和dns的地址 3、将如下内容写入/etc/hosts文件中(如果有多个ip地址则写多行&…...
国标GB28181视频平台EasyCVR顺应智慧农业自动化趋势,打造大棚实时视频监控防线
一、方案背景 近年来,温室大棚种植技术凭借其显著的优势,在提升农作物产量和质量、丰富农产品供应方面发挥了重要的作用,极大改善了人们的生活水平,得到了广泛的推广和应用。大棚内的温度、湿度、光照度和二氧化碳浓度等环境因素…...
HOW - 如何测试 React 代码
目录 一、使用 React 测试库:testing-library/react二、使用测试演练场:testing-playground.com三、使用 Cypress 或 Playwright 进行端到端测试四、使用 MSW 在测试中模拟网络请求 一、使用 React 测试库:testing-library/react testing-li…...
LU分解原理与C++实现:从理论到实践
LU分解原理与C++实现:从理论到实践 a. LU分解基础理论 矩阵的LU分解在数值计算领域占据着举足轻重的地位,它不仅是解决线性方程组的有力工具,还在众多科学与工程问题中发挥着关键作用。从数学定义来看,LU分解是将一个方阵 A A A 分解为一个单位下三角矩阵 L L L 和一个…...
【Vue3知识】组件间通信的方式
组件间通信的方式 概述**1. 父子组件通信****父组件向子组件传递数据(Props)****子组件向父组件发送事件(自定义事件)** **2. 兄弟组件通信****通过父组件中转****使用全局状态管理(如 Pinia 或 Vuex)** **…...
HOOPS Visualize:跨平台、高性能的三维图形渲染技术解析
在当今数字化时代,三维可视化技术已成为众多行业的核心竞争力。HOOPS Visualize作为一款功能强大的三维图形渲染引擎,凭借其卓越的渲染能力、跨平台支持、丰富的交互功能、高度定制化以及快速部署等特性,为开发人员提供了构建高质量、高性能3…...
git 的常用指令
以下是 Git 命令分类大全,覆盖日常开发、团队协作和高级操作场景,按功能分类整理: 一、配置与初始化 命令说明git config --global user.name "Your Name"设置全局用户名git config --global user.email "emailexample.com&q…...
python学智能算法(九)|决策树深入理解
【1】引言 前序学习进程中,初步理解了决策树的各个组成部分,此时将对决策树做整体解读,以期实现深入理解。 各个部分的解读文章链接为: python学智能算法(八)|决策树-CSDN博客 【2】代码 【2.1】完整代…...
蓝桥杯 C/C++ 组历届真题合集速刷(一)
一、1.单词分析 - 蓝桥云课 (模拟、枚举)算法代码: #include <bits/stdc.h> using namespace std;int main() {string s;cin>>s;unordered_map<char,int> mp;for(auto ch:s){mp[ch];}char result_charz;int max_count0;fo…...
多类型医疗自助终端智能化升级路径(代码版.上)
大型医疗自助终端的智能化升级是医疗信息化发展的重要方向,其思维链一体化路径需要围绕技术架构、数据流协同、算法优化和用户体验展开: 一、技术架构层:分布式边缘计算与云端协同 以下针对技术架构层的分布式边缘计算与云端协同模块,提供具体编程实现方案: 一、边缘节点…...
区间 DP 详解
文章目录 区间 DP分割型合并型环形合并 区间 DP 区间 DP,就是在对一段区间进行了若干次操作后的最小代价,一般是合并和拆分类型。 分割型 分割型,指把一个区间内的几项分开拆成一份一份的,再全部合起来就是当前答案,…...
如何在多线程中安全地使用 PyAudio
1. 背景介绍 在多线程环境下使用 PyAudio 可能会导致段错误(Segmentation Fault)或其他不可预期的行为。这是因为 PyAudio 在多线程环境下可能会出现资源冲突或线程安全问题。 PyAudio 是一个用于音频输入输出的 Python 库,它依赖于 PortAu…...
QAM 信号的距离以及能量归一化
QAM星座图平均功率能量_星座图功率计算-CSDN博客 正交幅度调制(QAM) - Vinson88 - 博客园 不同阶QAM调制星座图中,符号能量的归一化计算原理_qpsk的星座图归一化-CSDN博客 https://zhuanlan.zhihu.com/p/690157236...
Reactive编程框架与工具
文章目录 6.2 后端 Reactive 框架6.2.1 Spring WebFlux核心架构核心组件实际应用高级特性性能优化适用场景与限制 6.2.2 Akka(Actor模型)Actor模型基础基本用法高级特性响应式特性实现性能优化实际应用场景优势与挑战 6.2.3 Vert.x(事件驱动&…...
五子棋游戏开发:静态资源的重要性与设计思路
以下是以CSDN博客的形式整理的关于五子棋游戏静态资源需求的文章,基于我们之前的讨论,内容结构清晰,适合开发者阅读和参考。我尽量保持技术性、实用性,同时加入一些吸引读者的亮点。 五子棋游戏开发:静态资源的重要性与…...
Python爬虫第7节-requests库的高级用法
目录 前言 一、文件上传 二、Cookies 三、会话维持 四、SSL证书验证 五、代理设置 六、超时设置 七、身份认证 八、Prepared Request 前言 上一节,我们认识了requests库的基本用法,像发起GET、POST请求,以及了解Response对象是什么。…...
Maven的安装配置-项目管理工具
各位看官,大家早安午安晚安呀~~~ 如果您觉得这篇文章对您有帮助的话 欢迎您一键三连,小编尽全力做到更好 欢迎您分享给更多人哦 今天我们来学习:Maven的安装配置-项目管理工具 目录 1.什么是Maven?Maven用来干什么的?…...
智能 SQL 优化工具 PawSQL 月度更新 | 2025年3月
📌 更新速览 本月更新包含 21项功能增强 和 9项问题修复,重点提升SQL解析精度与优化建议覆盖率。 一、SQL解析能力扩展 ✨ 新增SQL语法解析支持 SELECT...INTO TABLE 语法解析(3/26) ALTER INDEX RENAME/VISIBLE 语句解析&#…...
Ubuntu虚拟机编译安装部分OpenCV模块方法实现——保姆级教程
Ubuntu虚拟机的安装过程可以查看另一篇文章:VMware安装Ubuntu虚拟机实现COpenCV代码在虚拟机下运行教程-CSDN博客 目前我们已经下载好了OpenCV,这里以OpenCV4.5.2为例。 在内存要求尽可能小的情况下,可以尝试只编译安装代码中使用到的OpenC…...
find指令中使用正则表达式
linux查找命令能结合正则表达式吗 find命令要使用正则表达式需要结合-regex参数 另,-type参数可以指定查找类型(f为文件,d为文件夹) rootlocalhost:~/regular_expression# ls -alh 总计 8.0K drwxr-xr-x. 5 root root 66 4月 8日 16:26 . dr-xr-…...
Java Web从入门到精通:全面探索与实战(二)
Java Web从入门到精通:全面探索与实战(一)-CSDN博客 目录 四、Java Web 开发中的数据库操作:以 MySQL 为例 4.1 MySQL 数据库基础操作 4.2 JDBC 技术深度解析 4.3 数据库连接池的应用 五、Java Web 中的会话技术ÿ…...
基于大模型的阵发性室上性心动过速风险预测与治疗方案研究
目录 一、引言 1.1 研究背景与意义 1.2 研究目的与目标 1.3 研究方法与数据来源 二、阵发性室上性心动过速概述 2.1 定义与分类 2.2 发病机制与流行病学 2.3 临床表现与诊断方法 三、大模型在阵发性室上性心动过速预测中的应用 3.1 大模型技术原理与特点 3.2 模型构…...
秒杀业务的实现过程
一.后台创建秒杀的活动场次信息,并关联到要秒杀的商品或服务; 二.通过定时任务,将秒杀的活动信息和商品服务信息存储到redis; 三.在商品展示页的显眼位置加载秒杀活动信息; 四.用户参与秒杀,创建订单,将…...
spring mvc @ResponseBody 注解转换为 JSON 的原理与实现详解
ResponseBody 注解转换为 JSON 的原理与实现详解 1. 核心作用 ResponseBody 是 Spring MVC 的一个注解,用于将方法返回的对象直接序列化为 HTTP 响应体(如 JSON 或 XML),而不是通过视图解析器渲染为视图(如 HTML&…...
TDengine.C/C++ 连接器
简介 C/C 开发人员可以使用 TDengine 的客户端驱动,即 C/C 连接器(以下都用 TDengine 客户端驱动表示),开发自己的应用来连接 TDengine 集群完成数据存储、查询以及其他功能。TDengine 客户端驱动的 API 类似于 MySQL 的 C API。…...
