目录
[一、when 条件判断](#一、when 条件判断)
[1. 基于事实变量的判断](#1. 基于事实变量的判断)
[IP 地址判断](#IP 地址判断)
[2. 字符串匹配判断](#2. 字符串匹配判断)
[match 匹配(精确匹配开头)](#match 匹配(精确匹配开头))
[search 搜索(包含匹配)](#search 搜索(包含匹配))
[3. 多条件组合判断](#3. 多条件组合判断)
[1. 基础变量注册](#1. 基础变量注册)
[2. 基于注册变量的判断](#2. 基于注册变量的判断)
[3. 注册变量的常用属性](#3. 注册变量的常用属性)
[1. 基础循环](#1. 基础循环)
[2. 字典循环](#2. 字典循环)
[3. 循环与条件判断结合](#3. 循环与条件判断结合)
[四、handlers 触发器](#四、handlers 触发器)
[1. 基础 handlers](#1. 基础 handlers)
[2. handlers 与条件判断结合](#2. handlers 与条件判断结合)
[3. 多个 notify 触发](#3. 多个 notify 触发)
[五、ignore_errors 错误处理](#五、ignore_errors 错误处理)
[1. 忽略任务错误](#1. 忽略任务错误)
[2. 条件忽略错误](#2. 条件忽略错误)
[六、jinja2 模板](#六、jinja2 模板)
[1. 基本模板使用](#1. 基本模板使用)
[2. 模板中的条件判断](#2. 模板中的条件判断)
[3. 模板中的循环](#3. 模板中的循环)
[案例1:智能部署 Nginx](#案例1:智能部署 Nginx)
[1. when 判断](#1. when 判断)
[2. 变量注册](#2. 变量注册)
[3. 循环](#3. 循环)
[4. handlers](#4. handlers)
[5. 错误处理](#5. 错误处理)
[6. 模板](#6. 模板)
一、when 条件判断
when 是 Ansible 中最基本的条件判断语句,用于决定是否执行某个任务。它支持多种判断方式,可以结合事实变量(Facts)和注册变量使用。
1. 基于事实变量的判断
操作系统版本判断
- hosts: web01
tasks:
- name: 仅在 CentOS 系统上安装软件
yum:
name: wget
state: present
when: ansible_distribution == "CentOS"
- name: 不同系统安装不同软件
yum:
name: httpd
state: present
when: ansible_os_family == "RedHat"
- name: Ubuntu 系统使用 apt
apt:
name: apache2
state: present
when: ansible_distribution == "Ubuntu"
主机名判断
- hosts: webs
tasks:
- name: 只在 web01 上安装
yum:
name: wget
state: present
when: ansible_hostname == "web01"
IP 地址判断
- hosts: webs
tasks:
- name: 只在 10.0.0.8 上安装
yum:
name: wget
state: present
when: ansible_default_ipv4.address == "10.0.0.8"
- name: 除了 10.0.0.8,其他都安装
yum:
name: wget
state: present
when: ansible_default_ipv4.address != "10.0.0.8"
2. 字符串匹配判断
Ansible 提供了多种字符串匹配方式:
match 匹配(精确匹配开头)
- hosts: webs
tasks:
- name: 匹配以 web01 开头的主机
yum:
name: wget
state: present
when: ansible_hostname is match "web01"
- name: 除了 web01,其他都安装
yum:
name: wget
state: present
when: ansible_hostname is not match "web01"
search 搜索(包含匹配)
- hosts: webs
tasks:
- name: 主机名包含 web01 的执行
yum:
name: wget
state: present
when: ansible_hostname is search "web01"
- name: 主机名包含 web 的执行
yum:
name: wget
state: present
when: ansible_hostname is search "web"
正则表达式匹配
- hosts: webs
tasks:
- name: 匹配以 web 开头的主机
yum:
name: wget
state: present
when: ansible_hostname is match "web.*"
- name: 匹配以 web 开头,以数字结尾
yum:
name: wget
state: present
when: ansible_hostname is match "web[0-9]+$"
3. 多条件组合判断
and(且)关系
# 方法一:使用 and 关键字
- hosts: webs
tasks:
- name: 同时满足两个条件
yum:
name: wget
state: present
when: (ansible_hostname is match "web01") and (ansible_default_ipv4.address == "10.0.0.7")
# 方法二:使用列表形式(推荐)
- hosts: webs
tasks:
- name: 同时满足两个条件
yum:
name: wget
state: present
when:
- ansible_hostname is match "web01"
- ansible_default_ipv4.address == "10.0.0.7"
or(或)关系
- hosts: webs
tasks:
- name: 满足任意一个条件
yum:
name: wget
state: present
when: (ansible_hostname is match "web01") or (ansible_default_ipv4.address == "10.0.0.8")
二、变量注册与条件判断
1. 基础变量注册
- hosts: web01
tasks:
- name: 执行命令并注册结果
command: nginx -t
register: result_nginx
ignore_errors: yes # 忽略错误,继续执行
- name: 查看注册变量内容
debug:
msg: "{{ result_nginx }}"
2. 基于注册变量的判断
- hosts: web01
tasks:
- name: 检查 nginx 配置
command: nginx -t
register: nginx_check
ignore_errors: yes
- name: 显示返回码
debug:
msg: "返回码:{{ nginx_check.rc }}"
- name: 显示错误信息
debug:
msg: "{{ nginx_check.stderr_lines }}"
- name: 配置正确时才重启
systemd:
name: nginx
state: restarted
when: nginx_check.stderr_lines is search "ok"
# 或者使用返回码判断
# when: nginx_check.rc == 0
3. 注册变量的常用属性
| 属性 | 说明 | 示例 |
|---|---|---|
rc |
返回码 | 0 表示成功 |
stdout |
标准输出(字符串) | "nginx: ok" |
stdout_lines |
标准输出(列表) | ["nginx: ok"] |
stderr |
错误输出(字符串) | "nginx: error" |
stderr_lines |
错误输出(列表) | ["nginx: error"] |
changed |
是否变更 | true/false |
failed |
是否失败 | true/false |
三、循环语句(loop)
1. 基础循环
循环启动服务
- hosts: web01
tasks:
- name: 同时启动多个服务
systemd:
name: "{{ item }}"
state: started
enabled: yes
loop:
- nginx
- php-fpm
- redis
循环安装软件
- hosts: web01
tasks:
- name: 批量安装软件
yum:
name: "{{ item }}"
state: present
loop:
- wget
- lrzsz
- tree
- vim
循环创建文件
- hosts: web01
tasks:
- name: 批量创建文件
file:
path: /root/{{ item }}
state: touch
loop:
- 1.txt
- 2.txt
- 3.txt
2. 字典循环
基本字典循环
- hosts: web01
tasks:
- name: 创建不同属主属组的文件
file:
path: /root/{{ item.name }}
owner: "{{ item.owner }}"
group: "{{ item.group }}"
state: touch
loop:
- { name: 1.txt, owner: root, group: root }
- { name: 2.txt, owner: www, group: www }
带权限的字典循环
- hosts: web01
tasks:
- name: 创建文件并设置权限
file:
path: /root/{{ item.name }}
owner: "{{ item.owner }}"
group: "{{ item.group }}"
mode: "{{ item.mode }}"
state: touch
loop:
- { name: 1.txt, owner: root, group: root, mode: "0777" }
- { name: 2.txt, owner: www, group: www, mode: "0600" }
批量创建用户
- hosts: web01
tasks:
- name: 批量创建用户
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
shell: "{{ item.shell }}"
create_home: "{{ item.home }}"
state: present
loop:
- { name: test01, uid: 777, shell: /bin/bash, home: true }
- { name: test02, uid: 888, shell: /sbin/nologin, home: false }
- { name: test03, uid: 999, shell: /bin/bash, home: true }
3. 循环与条件判断结合
- hosts: webs
tasks:
- name: 根据不同主机创建不同用户
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
loop:
- { name: webuser, uid: 1001, host: web01 }
- { name: dbuser, uid: 1002, host: db01 }
when: ansible_hostname == item.host
四、handlers 触发器
1. 基础 handlers
- hosts: web01
tasks:
- name: 安装 Nginx
yum:
name: nginx
state: present
- name: 配置 Nginx
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: Restart Nginx Server # 监控配置文件变化
- name: 启动 Nginx
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: Restart Nginx Server # notify 触发这里
systemd:
name: nginx
state: restarted
2. handlers 与条件判断结合
- hosts: web01
tasks:
- name: 安装 Nginx
yum:
name: nginx
state: present
- name: 配置 Nginx
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: Restart Nginx Server
- name: 检查 Nginx 配置
command: nginx -t
register: nginx_check
ignore_errors: yes
- name: 启动 Nginx
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: Restart Nginx Server
systemd:
name: nginx
state: restarted
when: nginx_check.rc == 0 # 配置正确才重启
3. 多个 notify 触发
- hosts: web01
tasks:
- name: 更新配置文件1
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify:
- Restart Nginx
- Check Nginx Config
- name: 更新配置文件2
copy:
src: php.ini
dest: /etc/php.ini
notify: Restart PHP-FPM
handlers:
- name: Restart Nginx
systemd:
name: nginx
state: restarted
- name: Check Nginx Config
command: nginx -t
- name: Restart PHP-FPM
systemd:
name: php-fpm
state: restarted
五、ignore_errors 错误处理
1. 忽略任务错误
- hosts: web01
tasks:
- name: 执行可能失败的命令
command: nginx -t
register: result
ignore_errors: yes # 即使失败也继续执行
- name: 继续执行后续任务
debug:
msg: "命令执行结果:{{ result.rc }}"
2. 条件忽略错误
- hosts: web01
tasks:
- name: 检查服务状态
command: systemctl status nginx
register: service_status
ignore_errors: "{{ ansible_distribution == 'CentOS' }}"
# 只在 CentOS 上忽略错误
六、jinja2 模板
1. 基本模板使用
{# motd 模板文件 #}
Welcome to {{ ansible_hostname }}
This system ipaddress: {{ ansible_default_ipv4.address }}
操作系统:{{ ansible_distribution }} {{ ansible_distribution_version }}
CPU核心:{{ ansible_processor_vcpus }}
内存大小:{{ ansible_memtotal_mb }} MB
- hosts: webs
tasks:
- name: 使用模板生成文件
template:
src: motd
dest: /etc/motd
2. 模板中的条件判断
{# nginx.conf.j2 #}
user www;
worker_processes {{ ansible_processor_vcpus * 2 }};
{% if ansible_memtotal_mb > 8000 %}
worker_connections 4096;
{% else %}
worker_connections 1024;
{% endif %}
{% if ansible_distribution_major_version == "7" %}
use epoll;
{% endif %}
3. 模板中的循环
{# hosts.j2 #}
127.0.0.1 localhost localhost.localdomain
{{ ansible_default_ipv4.address }} {{ ansible_hostname }}
{% for host in groups['webs'] %}
{{ hostvars[host].ansible_default_ipv4.address }} {{ hostvars[host].ansible_hostname }}
{% endfor %}
七、综合应用案例
案例1:智能部署 Nginx
- hosts: webs
vars:
nginx_port: 80
max_workers: "{{ ansible_processor_vcpus * 2 }}"
tasks:
- name: 检查操作系统
fail:
msg: "仅支持 CentOS 系统"
when: ansible_os_family != "RedHat"
- name: 安装 Nginx
yum:
name: nginx
state: present
- name: 生成 Nginx 配置
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Check and Restart Nginx
- name: 创建网站目录
file:
path: /var/www/html
state: directory
owner: nginx
group: nginx
mode: '0755'
- name: 部署网站文件
copy:
src: "{{ item }}"
dest: /var/www/html/
loop:
- index.html
- style.css
- script.js
when: ansible_hostname is match "web*"
- name: 启动 Nginx
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: Check and Restart Nginx
block:
- name: Check Nginx Config
command: nginx -t
register: check_result
- name: Restart Nginx
systemd:
name: nginx
state: restarted
when: check_result.rc == 0
- name: 配置错误告警
debug:
msg: "Nginx 配置错误,请检查!"
when: check_result.rc != 0
案例2:批量用户管理
- hosts: all
vars:
users:
- name: dev1
uid: 2001
groups: dev
shell: /bin/bash
home: true
- name: dev2
uid: 2002
groups: dev
shell: /bin/bash
home: true
- name: ops1
uid: 3001
groups: ops
shell: /bin/bash
home: true
- name: nginx
uid: 666
groups: www
shell: /sbin/nologin
home: false
tasks:
- name: 创建用户组
group:
name: "{{ item }}"
state: present
loop:
- dev
- ops
- www
- name: 批量创建用户
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
group: "{{ item.groups }}"
shell: "{{ item.shell }}"
create_home: "{{ item.home }}"
state: present
loop: "{{ users }}"
register: user_creation
- name: 显示创建结果
debug:
msg: "用户 {{ item.item.name }} 创建成功"
loop: "{{ user_creation.results }}"
when: not item.failed
- name: 为开发人员配置 sudo
copy:
content: "%dev ALL=(ALL) ALL"
dest: /etc/sudoers.d/dev
validate: 'visudo -cf %s'
when: ansible_hostname is search "dev"
案例3:服务自动伸缩
- hosts: webs
tasks:
- name: 获取系统负载
command: uptime
register: system_load
- name: 根据负载调整 Nginx 进程数
lineinfile:
path: /etc/nginx/nginx.conf
regexp: '^worker_processes'
line: "worker_processes {{ ansible_processor_vcpus * (2 if load_high else 1) }};"
vars:
load_high: "{{ ansible_processor_vcpus * 1.5 | float < system_load.stdout.split()[-2] | float }}"
notify: Restart Nginx
- name: 根据内存调整缓存大小
template:
src: nginx_cache.conf.j2
dest: /etc/nginx/conf.d/cache.conf
vars:
cache_size: "{{ (ansible_memtotal_mb * 0.2) | int }}M"
notify: Restart Nginx
handlers:
- name: Restart Nginx
systemd:
name: nginx
state: restarted
八、知识点小结
1. when 判断
-
基础比较 :
==、!=、>、<、>=、<= -
字符串匹配 :
match(开头匹配)、search(包含匹配) -
逻辑运算 :
and(且)、or(或) -
变量判断 :
is defined、is not defined
2. 变量注册
register: variable_name
debug: msg="{{ variable_name }}"
debug: msg="{{ variable_name.stdout_lines }}"
3. 循环
-
列表循环 :
loop: [item1, item2] -
字典循环 :
loop: [{key1: value1}, {key2: value2}] -
访问循环结果 :
{``{ item }}、{``{ item.key }}
4. handlers
-
触发 :
notify: handler_name -
定义 :在
handlers部分定义 -
特点:只在被 notify 时执行,且只执行一次
5. 错误处理
-
忽略错误 :
ignore_errors: yes -
失败处理 :
failed_when: condition -
强制失败 :
fail模块
6. 模板
-
变量替换 :
{``{ variable }} -
条件判断 :
{% if condition %}...{% endif %} -
循环 :
{% for item in list %}...{% endfor %}
这些条件判断和流程控制功能使得 Ansible Playbook 更加智能和灵活,能够根据不同的环境和条件执行不同的操作。