Ansible 核心功能:循环、过滤器、判断与错误处理全解析

Ansible 核心功能:循环、过滤器、判断与错误处理全解析

本文基于Ansible实践场景,系统梳理循环迭代数据过滤条件判断错误处理的核心用法,包含可直接复用的示例代码与关键注意事项,适用于Ansible自动化运维场景的学习与实战。

一、Ansible 循环迭代

循环用于批量执行重复任务(如安装多个软件、拷贝多个文件),Ansible支持传统with_*系列迭代器与现代loop(推荐配合过滤器使用)。

1. 传统 with_* 循环(适用于简单场景)

(1)with_items:迭代列表

用途 :批量处理列表中的元素(如安装多个软件包、创建多个文件)。
核心逻辑{``{ item }} 代表列表中的每个元素。

yaml 复制代码
---
- name: with_items test
  hosts: node1
  tasks:
    - name: debug1
      debug:
        msg: "{{ item }}"
      with_items:
        - aaa
        - bbb
        - ccc
        
(2)with_dict:迭代字典

用途 :处理键值对数据(如配置网络参数、批量设置变量)。
核心逻辑{``{ item.key }} 取字典的键,{``{ item.value }} 取字典的值。

yaml 复制代码
# 示例:打印网络参数(键-值对应)
---
- name: with_dict test
  hosts: all
  tasks:
    - name: aaaa
      debug:
        msg: "{{ item.key }} | {{ item.value }}"
      with_dict:
        name:  "{{ ansible_hostname }}"
        address: "{{ ansible_enp1s0.ipv4.address }}"
        dns: "{{ ansible_fqdn }}"
(3)with_fileglob:迭代文件(按路径匹配)

用途 :批量处理指定路径下的文件(如拷贝所有.sh.py脚本)。
注意 :路径为Ansible控制节点的路径,非受控节点。

yaml 复制代码
# 示例:批量拷贝控制节点/tmp下的.sh和.py文件到受控节点/tmp
---
- name: with_fileglob test
  hosts: node1
  tasks:
    - name: copy .sh and .py files
      copy:
        src: "{{ item }}"  # item遍历匹配到的文件
        dest: /tmp/
      with_fileglob:
        - /tmp/*.sh
        - /tmp/*.py
(4)with_lines:迭代命令输出(按行)

用途 :将Linux命令的输出按行作为迭代元素(如处理find找到的文件)。

yaml 复制代码
# 示例:拷贝find命令找到的所有.yml文件到受控节点/tmp
---
- name: with_lines test
  hosts: node1
  tasks:
    - name: copy ansible yml files
      copy:
        src: "{{ item }}"
        dest: /tmp/
      with_lines:
        - find /etc/ansible -name "*.yml"  # 命令输出按行迭代
(5)with_nested:嵌套迭代

用途 :实现多列表的"笛卡尔积"组合(如A列表每个元素与B列表所有元素匹配)。
核心逻辑{``{ item[0] }} 取第一个列表元素,{``{ item[1] }} 取第二个列表元素。

yaml 复制代码
# 示例:列表[a,b]与[1,2,3]嵌套组合
- name: with_nested test
  hosts: node1
  tasks:
    - name: print combined pairs
      debug:
        msg: "字母:{{ item[0] }} | 数字:{{ item[1] }}"
      with_nested:
        - [a, b]    # 第一个列表(index 0)
        - [1, 2, 3] # 第二个列表(index 1)
# 输出结果:a&1、a&2、a&3、b&1、b&2、b&3
(6)with_sequence:生成有序序列

用途 :生成连续数字序列(如创建编号文件、批量命名)。
参数start(起始值)、end(结束值)、stride(步长)。

yaml 复制代码
# 示例:生成1-5的序列(步长1)
- name: with_sequence test
  hosts: node1
  tasks:
    - name: print sequence
      debug:
        msg: "当前数字:{{ item }}"
      with_sequence:
        start=1
        end=5
        stride=1  # 每次递增1
(7)with_random_choice:随机取列表元素

用途:从列表中随机选择一个元素(如随机选择测试节点、随机生成值)。

yaml 复制代码
# 示例:随机输出列表中的一个元素
- name: random choice
  hosts: node1
  tasks:
    - name: print random item
      debug:
        msg: "随机选中:{{ item }}"
      with_random_choice:
        - 1
        - 2
        - a
        - b
        - c

2. 现代 loop(推荐)

loop 是Ansible推荐的新一代循环语法,需配合过滤器 (如listdict2items)使用,功能更灵活。

  • 替代with_itemsloop: [元素1, 元素2, ...]
  • 替代with_dictloop: "{``{ 字典 | dict2items }}"(此时item.key/item.value仍可用)
yaml 复制代码
# 示例1:用loop替代with_items(批量安装软件)
---
- name: with_dict test
  hosts: all
  tasks:
    - name: aaaa
      debug:
        msg: "{{ item }}"
      loop:
        - 12345678
        - abcdefgh
        - ABCDEFGH

    - name: bbbb
      debug:
        msg: "{{ item.key }} -> {{ item.value }}"
      loop: "{{
        {  
          'name': ansible_hostname, 
          'address': ansible_default_ipv4.address, 
          'dns': ansible_fqdn 
        } | dict2items 
      }}"

二、Ansible 过滤器

过滤器用于数据转换与处理 (如字符串大小写、数字类型转换、密码哈希),语法为{``{ 变量 | 过滤器(参数) }}

1. 字符串相关过滤器

处理字符串格式、长度、截取等,常见场景:配置文件内容格式化、变量清洗。

  • upper :将字符串转为纯大写。

    示例代码:{``{ "abc123ABC" | upper }},输出结果:ABC123ABC

  • lower :将字符串转为纯小写。

    示例代码:{``{ "abc123ABC" | lower }},输出结果:abc123abc

  • capitalize :将字符串首字母转为大写,其余字母转为小写。

    示例代码:{``{ "abc123ABC" | capitalize }},输出结果:Abc123abc

  • trim :去除字符串首尾的空格(中间空格保留)。

    示例代码:{``{ " abc " | trim }},输出结果:abc

  • length/count :计算字符串的长度(字符个数),两者功能完全等效。

    示例代码:{``{ "abc123" | length }},输出结果:6

  • first :获取字符串的第一个字符。

    示例代码:{``{ "abc123" | first }},输出结果:a

  • last :获取字符串的最后一个字符。

    示例代码:{``{ "abc123" | last }},输出结果:3

  • center(width) :将字符串居中显示,总长度固定为width,不足部分用空格补全。

    示例代码:{``{ "abc" | center(10) }},输出结果:abc(前后各3个空格,总长度10)。

  • list :将字符串拆分为字符列表,每个字符作为列表的一个元素。

    示例代码:{``{ "1a2b" | list }},输出结果:['1','a','2','b']

  • shuffle :先将字符串拆分为字符列表,再随机打乱列表中元素的顺序(每次执行结果可能不同)。

    示例代码:{``{ "1a2b" | shuffle }},可能的输出结果:['a','2','1','b']

2. 数字相关过滤器

处理数字类型转换、计算、随机数生成,解决Ansible中"字符串与数字无法直接运算"的问题。

  • int(default=值) :将输入转为整数,若无法转换(如输入为非数字字符串),则返回默认值(默认值不指定时为0)。

    示例1(正常转换):{``{ "8" | int }},输出结果:8

    示例2(无法转换):{``{ "a" | int(6) }},输出结果:6

  • float(default=值) :将输入转为浮点数,若无法转换,返回默认值(默认值不指定时为0.0)。

    示例1(正常转换):{``{ "8.5" | float }},输出结果:8.5

    示例2(无法转换):{``{ "a" | float(8.88) }},输出结果:8.88

  • abs :获取数字的绝对值(对负数生效,正数不变)。

    示例代码:{``{ -10 | abs }},输出结果:10

  • round(n) :对数字进行四舍五入,n指定保留的小数位数(不指定时默认保留0位,即整数)。

    示例1(保留整数):{``{ 12.5 | round }},输出结果:13

    示例2(保留3位小数):{``{ 3.14159 | round(3) }},输出结果:3.142

  • random(start=值, step=值) :生成随机数,默认范围是"0到过滤器前的数字";start指定随机数的起始值,step指定随机数的递增步长(即随机数只能是"start + 整数×step")。

    示例1(0-100的随机整数):{``{ 100 | random }},可能输出:45

    示例2(5-15、步长3的随机数):{``{ 15 | random(start=5, step=3) }},可能输出:581114中的一个。

3. 文件/密码相关过滤器

用于文件校验、密码哈希(安全存储密码,避免明文),常见于用户创建、配置文件校验场景。

  • hash(算法) :对字符串进行哈希计算,支持的算法包括md5sha1sha256等,相同输入会生成固定的哈希值。

    示例代码:{``{ "123456" | hash("md5") }},输出结果为e10adc3949ba59abbe56e057f20f883e(固定md5值)。

  • checksum :功能与hash("md5")完全等效,常用于文件内容的校验(判断文件是否被修改)。

    示例代码:{``{ "123456" | checksum }},输出结果与hash("md5")一致,。

  • password_hash(算法, 盐) :对密码进行哈希处理(推荐使用sha512算法,安全性高),为可选参数------不指定时自动生成随机盐(避免彩虹表破解),指定时用自定义字符串作为盐。

    示例1(自动生成盐):{``{ "redhat" | password_hash("sha512") }},输出结果为带随机盐的sha512哈希值(每次执行不同);

    示例2(自定义盐):{``{ "redhat" | password_hash("sha512", "mysalt") }},输出结果为固定的sha512哈希值(盐固定,结果固定)。

实战场景:创建用户并设置哈希密码(避免明文存储)

yaml 复制代码
- name: create user with hashed password
  hosts: node1
  tasks:
    - name: create user chenyu
      user:
        name: chenyu
        password: "{{ 'redhat' | password_hash('sha512') }}"  # 哈希存储密码,自动生成盐
        state: present

三、Ansible 条件判断(When)

when 用于根据条件决定任务是否执行,支持运算符Tests(断言) 两种判断方式。

1. 常用运算符

用于比较变量值、组合条件:

  • 比较运算符:==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)
  • 逻辑运算符:and(且,两个条件同时满足)、or(或,任意一个条件满足)、not(非,否定条件)
  • 成员运算符:in(判断元素是否在列表/字符串中)、not in(判断元素是否不在列表/字符串中)
yaml 复制代码
# 示例:当变量aa等于11且变量bb包含"test"时,执行debug任务
- name: condition with operators
  debug:
    msg: "条件满足,执行此任务"
  when: aa == 11 and "test" in bb

2. 常用 Tests(断言)

Tests 是Ansible预定义的判断逻辑,格式为变量 is Test,覆盖变量状态、任务结果、路径类型等场景。

(1)变量相关 Tests

判断变量是否定义、是否为空,常用于避免"未定义变量导致剧本报错":

  • defined :变量已被定义(无论值是否为空),则条件为真。

    示例代码:when: aa is defined(若aa: 11aa: "",均满足条件)。

  • undefined :变量未被定义(未在vars或 inventory 中声明),则条件为真。

    示例代码:when: bb is undefined(若未声明bb,满足条件)。

  • none :变量已定义,但值为空(如空字符串、空列表、空字典),则条件为真。

    示例代码:when: cc is none(若cc: ""cc: [],满足条件)。

yaml 复制代码
# 示例:变量状态判断
- name: test variable status
  hosts: node1
  vars:
    aa: 11    # 已定义且有值
    cc: ""    # 已定义但为空
  tasks:
    - debug: msg="aa已定义" when: aa is defined
    - debug: msg="bb未定义" when: bb is undefined
    - debug: msg="cc已定义但为空" when: cc is none
(2)任务结果相关 Tests

判断上一个任务的执行状态(需先用register将任务结果注册为变量),常用于"根据前序任务结果决定后续操作":

  • success/succeeded :前序任务执行成功(退出码为0),则条件为真,两者功能等效。

    示例代码:when: task_result is success

  • failure/failed :前序任务执行失败(退出码非0),则条件为真,两者功能等效。

    示例代码:when: task_result is failed

  • changed :前序任务导致受控节点的系统状态发生变化(如创建文件、修改配置),则条件为真。

    示例代码:when: task_result is changed

  • skipped :前序任务因条件不满足被跳过(未执行),则条件为真。

    示例代码:when: task_result is skipped

yaml 复制代码
# 示例:判断ls /mnt任务的执行结果
- name: test task result
  hosts: node1
  tasks:
    - name: list /mnt directory
      shell: ls /mnt
      register: ls_result  # 将任务结果注册为变量ls_result

    - debug: msg="ls /mnt执行成功" when: ls_result is success
    - debug: msg="ls /mnt执行失败" when: ls_result is failed
    - debug: msg="ls /mnt导致系统状态变化" when: ls_result is changed
(3)路径相关 Tests

判断Ansible控制节点上路径的类型(注意:不是受控节点!),常用于"执行文件操作前校验路径":

  • file :路径指向一个普通文件(非目录、非链接),则条件为真。
    示例代码:when: /tmp/test.sh is file
  • directory :路径指向一个目录(非文件、非链接),则条件为真。
    示例代码:when: /tmp/data is directory
  • link :路径指向一个软链接(无论链接目标是否存在),则条件为真。
    示例代码:when: /tmp/link.sh is link
  • mount :路径是一个已挂载的挂载点(即mount命令可查看到该路径),则条件为真。
    示例代码:when: /boot is mount
  • exists :路径存在(无论路径是文件、目录还是链接),则条件为真。
    示例代码:when: /tmp/test.sh is exists

创建相关文件

bash 复制代码
student@master tmp]$ touch test.sh
[student@master tmp]$ mkdir data
[student@master tmp]$ ln -s test.sh link.sh
[student@master tmp]$ ln test.sh hardlink.sh

编写剧本

yaml 复制代码
---
- name: with_dict test
  hosts: node1
  tasks:

    - name: aaaa
      debug:
        msg: '/tmp/test.sh is file'
      when: "'/tmp/test.sh' is file"

    - name: bbbb
      debug:
        msg: '/tmp/data is directory'
      when: "'/tmp/data' is directory"

    - name: cccc
      debug:
        msg: '/tmp/link.sh is link'
      when: "'/tmp/link.sh' is link"

    - name: dddd
      debug:
        msg: '/tmp/hardlink.sh is link'
      when: "'/tmp/hardlink.sh' is link"

    - name: eeee
      debug:
        msg: '/boot is mount'
      when: "'/boot' is mount "

    - name: ffff
      debug:
        msg: '/tmp/test.sh is exists'
      when: "'/tmp/test.sh' is exists "

运行剧本

bash 复制代码
TASK [aaaa] ********************************************************************************
ok: [node1] => {
    "msg": "/tmp/test.sh is file"
}

TASK [bbbb] ********************************************************************************
ok: [node1] => {
    "msg": "/tmp/data is directory"
}

TASK [cccc] ********************************************************************************
ok: [node1] => {
    "msg": "/tmp/link.sh is link"
}

TASK [dddd] ********************************************************************************
skipping: [node1]

TASK [eeee] ********************************************************************************
ok: [node1] => {
    "msg": "/boot is mount"
}

TASK [ffff] ********************************************************************************
ok: [node1] => {
    "msg": "/tmp/test.sh is exists"
}

可以看到只有hredlink被跳过这是因为hredlink是硬链接属于普通文件

(4)其他 Tests

覆盖字符串格式、数据类型等判断场景:

  • lower :字符串中所有字母均为小写(非字母字符不影响),则条件为真。

    示例代码:when: "abc123" is lower(满足条件)、when: "aBc123" is lower(不满足条件)。

  • upper :字符串中所有字母均为大写(非字母字符不影响),则条件为真。

    示例代码:when: "ABC123" is upper(满足条件)、when: "ABc123" is upper(不满足条件)。

  • string :对象是字符串类型(即使内容是数字,如"123"),则条件为真。

    示例代码:when: "123" is string(满足条件)、when: 123 is string(不满足条件)。

  • number :对象是数字类型(整数或浮点数,如1233.14),则条件为真。

    示例代码:when: 123 is number(满足条件)、when: "123" is number(不满足条件)。

四、块处理(block/rescue/always)

用于批量控制任务的错误处理 ,实现"主任务-失败恢复-最终执行"的逻辑,类似编程语言中的try-catch-finally

  • block:定义"正常执行的主任务块",若块内任意任务失败,直接跳转到rescue
  • rescue:定义"失败恢复任务块",仅当block执行失败时才执行。
  • always:定义"最终执行任务块",无论block成功或失败,都会执行(常用于清理、收尾操作)。

实战场景:创建逻辑卷(LV)的错误处理

需求:在research卷组创建1500MiB的dataLV;若卷组不存在则提示错误;若空间不足则用800MiB创建,且最终需格式化LV为ext4。

yaml 复制代码
# 前提:node1的research卷组大小为2G(可创建1500MiB LV),node2的research卷组大小为1G(仅可创建800MiB LV)
---
- name: aaaaaa
  hosts: all 
  tasks:
    # 核心块:创建LV并处理失败
    - name: creat data
      block:
        # 主任务:尝试创建1500MiB的LV
        - name: create lv1
          lvol:
            vg: research
            lv: data
            size: 1500
            state: present
            
      rescue:
        # 恢复逻辑:创建失败(空间不足),输出错误信息并改用800MiB创建
        - name: not 1500
          debug:
            msg: "Could not create logical volume of that size"
            
        - name: create lv2
          lvol:
            vg: research
            lv: data
            size: 800M
      always:
        # 最终执行:无论LV是否创建成功,都将其格式化为ext4
        - name: filesystem
          filesystem:
            dev: /dev/research/data
            fstype: ext4
      when: "'research' in ansible_facts.lvm.vgs"  
      # 仅当卷组research存在时,执行该块

    # 卷组不存在时,输出提示信息
    - name: not research
      debug:
        msg: "Volume group does not exist"
      when: "'research' not in ansible_facts.lvm.vgs"

五、错误处理(fail/failed_when/ignore_errors/changed_when)

用于主动控制任务的执行状态(中断剧本、跳过错误、修改状态),确保剧本在异常场景下的可控性。

1. fail 模块:主动中断剧本

当满足特定条件时,主动中断当前剧本的执行,并输出自定义错误信息,常与when配合使用(需明确中断条件)。

yaml 复制代码
- name: interrupt playbook with fail module
  hosts: node1
  tasks:
    # 执行shell命令,输出含"error"的内容
    - name: execute shell command
      shell: echo "this is a test--error"
      register: cmd_result  # 将命令输出注册为变量

    # 当输出中包含"error"时,中断剧本
    - name: fail and stop playbook
      fail:
        msg: "Found 'error' in command output, stopping playbook now"  # 自定义错误信息
      when: "'error' in cmd_result.stdout"  # 中断条件:输出含"error"

    # 上方任务中断后,此任务不会执行
    - name: unreachable task
      debug:
        msg: "This task will not run because playbook is stopped"

运行效果

bash 复制代码
PLAY [aaaaaa] ******************************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [node5]
ok: [node3]
ok: [node4]
ok: [node1]
ok: [node2]

TASK [create lv1] **************************************************************************
skipping: [node3]
skipping: [node4]
skipping: [node5]
fatal: [node1]: FAILED! => {"changed": false, "err": "  Volume group \"research\" has insufficient free space (249 extents): 375 required.\n", "msg": "Creating logical volume 'data' failed", "rc": 5}
changed: [node2]

TASK [dddd] ********************************************************************************
ok: [node1] => {
    "msg": "Could not create logical volume of that size"
}

TASK [create lv2] **************************************************************************
changed: [node1]

TASK [filesystem] **************************************************************************
skipping: [node3]
skipping: [node4]
skipping: [node5]
changed: [node1]
changed: [node2]

TASK [cccc] ********************************************************************************
skipping: [node1]
skipping: [node2]
ok: [node3] => {
    "msg": "Volume group does not exist"
}
ok: [node4] => {
    "msg": "Volume group does not exist"
}
ok: [node5] => {
    "msg": "Volume group does not exist"
}

2. failed_when:自定义任务失败条件

强制将"命令执行成功(退出码为0)的任务"标记为失败,无需依赖fail模块,直接通过条件控制任务状态。

yaml 复制代码
- name: custom failed condition with failed_when
  hosts: node1
  tasks:
    # 执行shell命令(退出码为0,默认标记为成功)
    - name: execute shell command
      shell: echo "this is a test--error"
      register: cmd_result
      # 自定义失败条件:输出含"error"时,将任务标记为失败
      failed_when: "'error' in cmd_result.stdout"

    # 上一步任务被标记为失败,剧本默认中断,此任务不执行
    - name: unreachable task
      debug:
        msg: "This task will not run because previous task failed"

3. ignore_errors: yes:跳过错误

当任务执行失败时(如命令退出码非0、变量未定义),忽略该错误并继续执行后续任务,不中断整个剧本。

yaml 复制代码
- name: ignore task errors with ignore_errors
  hosts: node1
  tasks:
    # 正常执行:打印受控节点的FQDN(ansible_fqdn为Ansible内置变量,已定义)
    - name: print controlled node's FQDN
      debug:
        msg: "FQDN: {{ ansible_fqdn }}"

    # 执行失败:打印未定义的变量ansible_ip,但忽略错误
    - name: print non-existent variable (ignore error)
      debug:
        msg: "IP: {{ ansible_ip }}"  # ansible_ip未定义,任务默认失败
      ignore_errors: yes  # 忽略此任务的失败,继续执行后续任务

    # 正常执行:创建/tmp/abc文件(因上一步错误被忽略,此任务可执行)
    - name: create /tmp/abc file
      file:
        path: /tmp/abc
        state: touch

4. changed_when:自定义任务状态

强制修改任务的changed状态(Ansible默认根据"任务是否修改系统"判断changed):

  • changed_when: true:无论任务是否修改系统,强制将状态标记为changed
  • changed_when: false:无论任务是否修改系统,强制将状态标记为ok
yaml 复制代码
- name: custom task status with changed_when
  hosts: node1
  tasks:
    # 强制标记为changed:debug任务默认不修改系统(状态为ok),此处强制改为changed
    - name: debug with forced changed status
      debug:
        msg: "FQDN: {{ ansible_fqdn }}"
      changed_when: true

    # 强制标记为ok:shell任务(ls /tmp)默认不修改系统(状态为ok),此处明确强制为ok
    - name: list /tmp directory with forced ok status
      shell: ls /tmp
      changed_when: false

小练习

http://ansible.example.com/materials/newhosts.j2 下载模板文件

完成该模板文件,用来生成新主机清单(主机的显示顺序没有要求),结构如下:

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4

::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.122.10 node1.example.com node1

192.168.122.20 node2.example.com node2

192.168.122.30 node3.example.com node3

192.168.122.40 node4.example.com node4

192.168.122.50 node5.example.com node5

创建剧本/home/student/ansible/newhosts.yml,它将使用上述模板在 node1 主机组的主机上

生成文件/etc/newhosts。

bash 复制代码
#下载模板
[student@master ansible]$ curl -O  http://ansible.example.com/materials/newhosts.j2 
#修改模板
{% for cy in groups.all %}
{{ hostvars[cy].ansible_default_ipv4.address}}  {{ hostvars[cy].ansible_fqdn }}  {{ hostvars[cy].ansible_hostname}}
{% endfor %}
编写剧本

---
- name: get fact
  hosts: all
- name: cp file
  hosts: node1
  tasks:
    - name: cp file
      template:
        src: /home/student/ansible/newhosts.j2
        dest: /etc/newhosts
#运行剧本        
#查看node1是否获取到了ip域名和主机名
[student@master ansible]$ ansible node1 -m shell -a 'cat /etc/newhosts'
node1 | CHANGED | rc=0 >>
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.122.10  node1.example.com  node1
192.168.122.20  node2.example.com  node2
192.168.122.30  node3.example.com  node3
192.168.122.40  node4.example.com  node4
192.168.122.50  node5.example.com  node5

编写剧本修改远程文件内容

创建剧本 /home/student/ansible/newissue.yml,满足下列要求:

1)在所有清单主机上运行,替换/etc/issue 的内容

2)对于 test01 主机组中的主机,/etc/issue 文件内容为 test01

3)对于 test02 主机组中的主机,/etc/issue 文件内容为 test02

4)对于 web 主机组中的主机,/etc/issue 文件内容为 Webserver

inventory

ini 复制代码
[test01]
node1

[test02]
node2

[web]
node3
node4

[test05]
node5

[webtest:children]
web

创建剧本

yaml 复制代码
---
- name: replace file
  hosts: all
  tasks:
    - name: test1
      copy:
        content: |
          {% if 'test01' in group_names %}
          test01
          {% elif 'test02' in group_names %}
          test02
          {% elif 'web' in group_names %}
          Webserver
          {% endif %}
        dest: /etc/issue

运行剧本后查看

bash 复制代码
[student@master ansible]$ ansible all -m shell -a 'cat /etc/issue'  
node1 | CHANGED | rc=0 >>
test01
node5 | CHANGED | rc=0 >>

node4 | CHANGED | rc=0 >>
Webserver
node3 | CHANGED | rc=0 >>
Webserver
node2 | CHANGED | rc=0 >>
test02
相关推荐
桦说编程3 小时前
使用注解写出更优雅的代码,以CFFU为例
java·后端·函数式编程
pythonpapaxia3 小时前
Java异常处理:掌握优雅捕获错误的艺术
java·开发语言·python·其他
kiwixing3 小时前
集群无法启动CRS-4124: Oracle High Availability Services startup failed
java·运维·数据库·mysql·postgresql·oracle
CZZDg3 小时前
部署jenkins并基于ansible部署Discuz应用
运维·ansible·jenkins
zzu123zsw3 小时前
第6章:垃圾回收分析与调优
java
Hygge-star3 小时前
【MySQL自学】SQL主键使用误区:你必须知道的关键细节
数据库·sql·mysql·数据分析·学习方法
向上的车轮3 小时前
SQL标准有哪些?由那个国际组织管理?国产数据库在SQL标准上的贡献有哪些?
数据库·sql·sql标准
Rhys..4 小时前
python sqlalchemy模型的建立
jvm·数据库·python·oracle
neo_Ggx234 小时前
SQL 函数:使用 REPLACE进行批量文本替换
数据库·sql