在Ansible Jinja模板中无法获取动态/其他主机的变量
Ansible模板hostvars引用语法错误解决
问题场景
通过变量final_delegate根据用户传入的perform_action参数决定Play2的目标主机,在生成HTML模板时引用hostvars出现语法错误。
相关Playbook代码
- name: "Play 1" hosts: localhost tasks: - set_fact: final_delegate: "{{ 'localhost' if perform_action in 'telnetcurlnslookuptracerouteget_ip_address' else 'dest_nodes' }}" - name: "Play 2" hosts: "{{ hostvars.localhost.final_delegate }}" tasks: - name: Run command ignore_errors: yes command: ls -ltr /tmp/all.pdf register: cmdoutput - name: Creating body template template: src: "{{ playbook_dir }}/body.html.j2" dest: "{{ playbook_dir }}/body.html.tmp" delegate_to: localhost
错误的模板代码(body.html.j2)
<tr> <td>{{ inventory_hostname }}</td> <td><pre>{{ hostvars.[inventory_hostname].cmdoutput.stdout_lines | join('\n') }}</pre></td> </tr>
报错信息
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: </tr> fatal: [localhost]: FAILED! => {"changed": false, "msg": "AnsibleError: template error while templating string: expected name or number. String: <tr>\n <td>{{ inventory_hostname }}</td>\n <td><pre>{{ hostvars.[inventory_hostname].cmdoutput.stdout_lines | join('\\n') }}</pre></td>\n </tr>\n\n"}
尝试过的错误写法
1. <td><pre>{{ hostvars.[hostvars.localhost.final_delegate].cmdoutput.stdout_lines | join('\n') }}</pre></td> 2. <td><pre>{{ hostvars.['hostvars.localhost.final_delegate'].cmdoutput.stdout_lines | join('\n') }}</pre></td>
错误原因
核心问题是hostvars的变量引用语法错误:
- Ansible中,若通过变量动态获取hostvars中的主机条目,必须使用
hostvars[变量名]的方括号语法; - 点语法(如
hostvars.localhost)仅适用于已知的固定主机名,不能在点后紧跟方括号(如hostvars.[变量名]),这属于语法违规。
正确写法建议
写法一:通过inventory_hostname动态获取(适用于Play2目标为单主机)
Play2的hosts参数是final_delegate,模板执行时inventory_hostname即为目标主机名,直接用方括号语法引用:
<tr> <td>{{ inventory_hostname }}</td> <td><pre>{{ hostvars[inventory_hostname].cmdoutput.stdout_lines | join('\n') }}</pre></td> </tr>
写法二:直接引用final_delegate对应的主机
若需明确指定final_delegate变量对应的主机,同样使用方括号语法解析变量:
<tr> <td>{{ hostvars.localhost.final_delegate }}</td> <td><pre>{{ hostvars[hostvars.localhost.final_delegate].cmdoutput.stdout_lines | join('\n') }}</pre></td> </tr>
注意事项
- 若
final_delegate是主机组(如dest_nodes),需遍历组内主机来获取每个主机的cmdoutput,可使用loop或with_items遍历groups[hostvars.localhost.final_delegate]; - 确保
cmdoutput变量已在目标主机的hostvars中存在(即Play2的Run command任务已成功执行)。
内容的提问来源于stack exchange,提问作者Ashar
相关产品推荐
相关产品推荐

