如何基于Facts条件执行命令并让同一Register存储不同命令输出?
F5设备Playbook优化问题解决
问题背景
现有Playbook目标是从多台F5设备提取Facts并执行特定Shell命令,当前存在两个核心问题:
- 如何通过
when条件选择执行不同命令集,避免第二个任务覆盖用于Jinja2模板的Register变量? - 如何让同一变量存储两个命令的输出而不被覆盖?用户推测合并任务是解决关键,但不知具体操作。
原Playbook代码
--- - name: Gather facts (f5) bigip_device_info: provider: "{{ provider }}" gather_subset: - system-info - devices register: dev_fact ####################### LTM Hosts ############################### - name: Task1.1 - Find vcmp count info shell: tmsh show vcmp health module-provision | grep 'ltm nominal' | grep ltm | wc -l when: not ( 'Z100'in dev_fact['system_info']['platform'] or 'Z101' in dev_fact['system_info']['platform'] ) ignore_errors: yes register: nommodltm failed_when: "'unexpected' in nommodltm.stdout" - name: "Set Fact for Nominal Module Count for LTM" set_fact: nommodltm={{ nommodltm.stdout_lines[0] }} ignore_errors: yes - name: Print lic info - vCMP Devices debug: msg: Lic LTM Nominal Info={{ nommodltm }} ####################### LTM VE | Guests ############################### - name: Task2.1 - Find vcmp count info shell: tmsh list sys provision | grep -b1 nominal | grep "sys provision ltm" | wc -l when: ( 'Z100'in dev_fact['system_info']['platform'] or 'Z101' in dev_fact['system_info']['platform'] ) ignore_errors: yes register: nommodltm failed_when: "'unexpected' in nommodltm.stdout" - name: "Set Fact for Nominal Module Count for LTM" set_fact: nommodltm={{ nommodltm.stdout_lines[0] }} ignore_errors: yes - name: Print device info - vCMP Devices debug: msg: Lic LTM Nominal Info={{ nommodltm }} - name: Copy output to file template: src: invchktest.txt.j2 dest: "inventory_check/{{ date }}-{{ dc }}-inventory_check.csv" delegate_to: localhost ignore_errors: true
解决方案
核心思路
通过合并任务逻辑+条件判断动态赋值,避免变量被覆盖,同时用统一变量存储最终结果。具体步骤:
- 用不同临时变量分别存储两个命令的执行结果
- 通过条件判断将对应临时变量的结果赋值给目标变量,确保同一变量只保留当前设备的正确结果
优化后的Playbook代码
--- - name: Gather facts (f5) bigip_device_info: provider: "{{ provider }}" gather_subset: - system-info - devices register: dev_fact # 提前定义平台判断变量,简化后续条件书写 - name: Set platform type flag set_fact: is_ve_guest: "{{ 'Z100' in dev_fact['system_info']['platform'] or 'Z101' in dev_fact['system_info']['platform'] }}" # 针对物理LTM主机执行命令,结果存临时变量 - name: Get vcmp count for physical LTM hosts shell: tmsh show vcmp health module-provision | grep 'ltm nominal' | grep ltm | wc -l when: not is_ve_guest ignore_errors: yes register: nommodltm_physical failed_when: "'unexpected' in nommodltm_physical.stdout" # 针对LTM VE/虚拟机执行命令,结果存另一个临时变量 - name: Get vcmp count for LTM VE/Guests shell: tmsh list sys provision | grep -b1 nominal | grep "sys provision ltm" | wc -l when: is_ve_guest ignore_errors: yes register: nommodltm_ve failed_when: "'unexpected' in nommodltm_ve.stdout" # 根据平台类型,将对应临时变量的结果赋值给最终变量 - name: Set final nominal module count set_fact: nommodltm: "{{ nommodltm_physical.stdout_lines[0] if not is_ve_guest else nommodltm_ve.stdout_lines[0] }}" ignore_errors: yes - name: Print lic info debug: msg: Lic LTM Nominal Info={{ nommodltm }} - name: Copy output to file template: src: invchktest.txt.j2 dest: "inventory_check/{{ date }}-{{ dc }}-inventory_check.csv" delegate_to: localhost ignore_errors: true
关键优化点
- 避免变量覆盖:用
nommodltm_physical和nommodltm_ve两个临时变量分别存储不同平台的命令结果,再统一赋值给nommodltm - 简化逻辑:提前定义
is_ve_guest变量,减少重复的条件判断代码,提升可读性 - 职责单一:每个任务只负责一件事,便于后续维护和调试
内容的提问来源于stack exchange,提问作者Tash
相关产品推荐
相关产品推荐

