如何在Ansible results的stdout_lines中搜字符串并按when条件执行新Play
Ansible 从register结果的stdout_lines中匹配字符串并控制任务执行
当你用with_items执行任务并通过register捕获结果时,play.results是一个列表,每个元素对应一次with_items迭代的任务输出。原代码里的when条件写法无法正确检查stdout_lines中的内容,以下是正确的实现方式:
核心说明
play.results里的每个元素包含stdout(命令输出字符串)、stdout_lines(按行拆分的输出列表)、item(当前迭代的用户)等字段。我们需要借助Ansible过滤器来筛选符合条件的结果。
场景1:只要存在一个匹配结果就执行任务
如果需要任意一个用户的执行结果包含目标字符串时触发后续任务,可这样写:
- hosts: server-a become: yes gather_facts: false vars_files: - filename.yml vars: target_string: "root" # 替换为你要搜索的目标字符串 tasks: - shell: whoami with_items: "{{ users }}" become_user: "{{ item }}" register: play - debug: msg: "System {{ inventory_hostname }} 存在匹配目标字符串的执行结果" when: play.results | selectattr('stdout_lines', 'contains', target_string) | list | length > 0
这里用selectattr过滤器筛选出stdout_lines包含目标字符串的结果,转成列表后判断长度是否大于0,只要有一个匹配就触发任务。
场景2:所有结果都匹配才执行任务
如果需要所有用户的执行结果都包含目标字符串才触发任务,可使用rejectattr反向筛选:
- debug: msg: "System {{ inventory_hostname }} 所有执行结果都匹配目标字符串" when: play.results | rejectattr('stdout_lines', 'contains', target_string) | list | length == 0
rejectattr会找出不匹配的结果,若结果列表长度为0,说明所有迭代的输出都符合要求。
场景3:针对每个匹配结果单独执行任务
如果需要对每个匹配的用户结果单独处理,可以直接遍历过滤后的结果列表:
- debug: msg: "用户 {{ item.item }} 的执行结果包含目标字符串:{{ item.stdout }}" loop: "{{ play.results | selectattr('stdout_lines', 'contains', target_string) | list }}"
这样每个符合条件的结果都会独立触发一次debug任务,输出对应的用户和执行结果。
原代码的问题点
原代码中的when: play['results'] contains specific string写法错误:
contains过滤器用于检查字符串是否包含子串,或列表是否包含某个完整元素play.results是任务结果的列表,直接使用会检查列表中是否存在等于specific string的元素,而非检查每个元素的stdout_lines内容
内容的提问来源于stack exchange,提问作者blue
相关产品推荐
相关产品推荐

