如何在Ansible Shell模块循环执行中重新为变量赋值
问题描述
我想要实现的逻辑如下:
cur_first_number = first_number.stdout for ip in groups[group_name] // 执行shell命令:检查文件中是否存在该IP,不存在则插入类似 `IP.{{ cur_first_number }} = {{ IP }}` 的行 // 当插入操作成功时,cur_first_number 自增 1
简单来说:从指定文件中检索IP,若该IP不存在,则插入格式为IP.{{ 序号 }} = {{ IP }}的行,且每成功插入一行,序号自动加1。
我当前的Ansible代码如下:
- name: 获取 openssl.cnf 中 [alt_names] 最后一行的起始数字 shell: grep -w "\[ req_distinguished_name \]" -B 2 "{{ openssl_cnf_path }}" | head -n 1 | grep -o "[0-9]*" | head -n 1 register: first_number delegate_to: localhost - name: 插入新行(IP.* = *.*.*.*)到匹配内容的下一行 shell: grep -e "{{ item }}" "{{ openssl_cnf_path }}" || sed -i "/{{ last_line.stdout }}/a\IP.{{ first_number.stdout | int + 1 }} = {{ item }}" "{{openssl_cnf_path}}" with_items: "{{ groups[group_name] }}" ignore_errors: true delegate_to: localhost
当前代码无法实现循环中cur_first_number自增的需求,请问如何在Shell模块的循环执行中重新为变量赋值?
解决方案
Ansible的with_items(或loop)循环中,每个迭代相互独立,直接用set_fact更新变量无法实时生效(Ansible变量更新为批次处理,循环结束后才会应用)。要实现你需要的逻辑,有两种可行思路:
思路1:Shell脚本内嵌循环处理
把完整逻辑写入Shell脚本,借助Shell原生的变量自增特性实现需求,能保证序号的连续性和实时更新:
- name: 获取初始序号 shell: grep -w "\[ req_distinguished_name \]" -B 2 "{{ openssl_cnf_path }}" | head -n 1 | grep -o "[0-9]*" | head -n 1 register: first_number delegate_to: localhost - name: 批量处理IP插入逻辑 shell: | cur_num={{ first_number.stdout | int }} last_line="{{ last_line.stdout }}" cnf_path="{{ openssl_cnf_path }}" for ip in {{ groups[group_name] | join(' ') }}; do # 检查IP是否已存在 if ! grep -q "$ip" "$cnf_path"; then # 插入新行 sed -i "/$last_line/a\IP.$cur_num = $ip" "$cnf_path" # 插入成功则自增序号 ((cur_num++)) fi done delegate_to: localhost
思路2:Ansible loop结合index预计算序号(限特定场景)
如果能确定所有待处理IP都不存在于目标文件中,可以用loop的index_var预计算每个IP对应的序号:
- name: 获取初始序号 shell: grep -w "\[ req_distinguished_name \]" -B 2 "{{ openssl_cnf_path }}" | head -n 1 | grep -o "[0-9]*" | head -n 1 register: first_number delegate_to: localhost - name: 插入新行(预计算序号) shell: grep -e "{{ item }}" "{{ openssl_cnf_path }}" || sed -i "/{{ last_line.stdout }}/a\IP.{{ first_number.stdout | int + idx + 1 }} = {{ item }}" "{{ openssl_cnf_path }}" loop: "{{ groups[group_name] | list }}" loop_control: index_var: idx ignore_errors: true delegate_to: localhost
注意:此方法局限性明显——若某个IP已存在不会插入,对应的序号会被跳过,导致后续序号不连续,仅适合所有IP都需要插入的场景。
内容的提问来源于stack exchange,提问作者鱼鱼鱼三条鱼
相关产品推荐
相关产品推荐

