Ansible 条件判断与流程控制详解

目录

[一、when 条件判断](#一、when 条件判断)

[1. 基于事实变量的判断](#1. 基于事实变量的判断)

操作系统版本判断

主机名判断

[IP 地址判断](#IP 地址判断)

[2. 字符串匹配判断](#2. 字符串匹配判断)

[match 匹配(精确匹配开头)](#match 匹配(精确匹配开头))

[search 搜索(包含匹配)](#search 搜索(包含匹配))

正则表达式匹配

[3. 多条件组合判断](#3. 多条件组合判断)

and(且)关系

or(或)关系

二、变量注册与条件判断

[1. 基础变量注册](#1. 基础变量注册)

[2. 基于注册变量的判断](#2. 基于注册变量的判断)

[3. 注册变量的常用属性](#3. 注册变量的常用属性)

三、循环语句(loop)

[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)

案例2:批量用户管理

案例3:服务自动伸缩

八、知识点小结

[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"
复制代码
- 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 definedis 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 更加智能和灵活,能够根据不同的环境和条件执行不同的操作。

相关推荐
志栋智能13 小时前
AI驱动的系统自动化巡检:重塑IT基石的智慧“守护神”
大数据·运维·人工智能·云原生·自动化
AI架构全栈开发实战笔记17 小时前
AI应用架构师教你:如何用AI自动化数据仓库的测试?
数据仓库·人工智能·ai·自动化
axPpcfNN21 小时前
可直接编译运行 c#解析dxf可读取圆直线弧多段线源码-无封装缩放拖拽 可读取坐标信息 支持多...
ansible
was1721 天前
Python 自动化实践:Typora 自定义上传接口与兰空图床集成
python·自动化·typora·兰空图床
工业HMI实战笔记1 天前
工业机器人HMI:协作机器人的人机交互界面
人工智能·ui·性能优化·机器人·自动化·人机交互·交互
工业HMI实战笔记1 天前
工业HMI色彩规范:4个禁忌+3类场景配色方案
ui·性能优化·自动化·汽车·交互
键盘鼓手苏苏2 天前
Flutter for OpenHarmony:git 纯 Dart 实现的 Git 操作库(在应用内实现版本控制) 深度解析与鸿蒙适配指南
开发语言·git·flutter·华为·rust·自动化·harmonyos
志栋智能2 天前
AI驱动的安全自动化机器人:从“告警疲劳”到“智能免疫”的防御革命
运维·人工智能·安全·机器人·自动化
志栋智能2 天前
自动化运维真的只能选复杂平台吗?
运维·网络·数据库·人工智能·自动化