Ansible vars_prompt引用前置交互变量报未定义的解决方法
报错根因
vars_prompt的所有配置会在playbook初始化阶段一次性完成解析,不会按配置的从上到下顺序,先完成一个变量的用户输入/默认值赋值,再解析下一个变量的配置。所以解析到SET_STEP2的default字段时,SET_STEP1还没走赋值流程,直接触发未定义错误,和SET_STEP1有没有配置默认值没有关系。
实现方法
方案1:用pause模块替代vars_prompt(推荐)
pause模块是在正式任务执行阶段运行的,严格遵循任务从上到下的执行顺序,前序变量赋值完成才会运行后续交互,天然支持变量依赖,交互体验和vars_prompt完全一致:
- hosts: localhost gather_facts: no tasks: - name: 交互获取SET_STEP1值 ansible.builtin.pause: prompt: "Set value for step 1" echo: yes register: step1_input vars: step1_default: "the value for step 1" set_fact: SET_STEP1: "{{ step1_input.user_input | default(step1_default, true) }}" - name: 交互获取SET_STEP2值 ansible.builtin.pause: prompt: "Set value for step 2 [默认值: {{ SET_STEP1 }} depends on the value of {{ SET_STEP1 }}]" echo: yes register: step2_input vars: step2_default: "{{ SET_STEP1 }} depends on the value of {{ SET_STEP1 }}" set_fact: SET_STEP2: "{{ step2_input.user_input | default(step2_default, true) }}" # 后续任务可直接引用两个变量 - debug: msg: - "STEP1取值: {{ SET_STEP1 }}" - "STEP2取值: {{ SET_STEP2 }}"
如果是密码类需要隐藏输入的场景,把对应pause任务的echo参数设为no即可。
方案2:兼容原生vars_prompt的写法
如果必须用vars_prompt,可以给依赖前置变量的默认值加未定义容错,避免初始化阶段解析报错,等所有prompt交互跑完,再在pre_tasks里把没手动输入的SET_STEP2覆盖为正确的默认值:
- hosts: localhost gather_facts: no vars_prompt: - name: SET_STEP1 prompt: "Set value for step 1" default: "the value for step 1" private: no - name: SET_STEP2 prompt: "Set value for step 2" # 初始化阶段SET_STEP1未定义时先用临时占位符,避免解析报错 default: "{% if SET_STEP1 is defined %}{{ SET_STEP1 }} depends on the value of {{ SET_STEP1 }}{% else %}__AUTO_DEFAULT__{% endif %}" private: no pre_tasks: - name: 补全SET_STEP2默认值 set_fact: SET_STEP2: "{{ SET_STEP1 }} depends on the value of {{ SET_STEP1 }}" when: SET_STEP2 == "__AUTO_DEFAULT__" tasks: - debug: msg: - "STEP1取值: {{ SET_STEP1 }}" - "STEP2取值: {{ SET_STEP2 }}"
这个方案的缺点是SET_STEP2的交互提示里没法提前展示依赖SET_STEP1的真实默认值,用户看到的默认提示是临时占位符,交互体验差一些,非必要不选。
注意事项
vars_prompt的加载时机是play启动的最早期,本身就不支持跨prompt的变量引用依赖,所有需要依赖其他变量动态生成默认值的交互场景,优先选pause模块的方案更稳妥。
内容的提问来源于stack exchange,提问作者GreNIX
相关产品推荐
相关产品推荐

