如何让Ansible任务文件同时支持include_tasks调用与独立运行?
问题描述
我有一些通用任务文件(比如基于本地机器向服务器更新DNS记录),目前通过include_tasks在多个Ansible剧本中调用,示例代码如下:
- name: (include) Update DNS include_tasks: task_update_dns.yml
这类通用任务作为共享任务被多个剧本使用,但有时我想直接在服务器上运行单个通用任务,执行命令:
ansible-playbook playbooks/task_update_dns.yml --limit $myserver
时会报错:
ERROR! 'set_fact' is not a valid attribute for a Play
原因是该文件仅为任务文件而非剧本,其内容示例如下:
文件:playbooks/task_update_dns.yml
--- - name: dig mydomain.com set_fact: my_hosts: '{{ lookup("dig", "mydomain.com").split(",") }}' tags: always - name: Set entries blockinfile: ....
我知道可以编写仅包含该任务文件的空剧本,但不想为每个任务都创建这类浅层次剧本,请问是否可配置任务文件使其同时支持include_tasks调用与独立运行?
解决方案
有两种可行的方法实现需求:
方法一:修改任务文件,兼容两种运行方式
在任务文件开头添加一个带条件判断的最小Play结构,仅当文件被直接作为剧本运行时才执行该Play;被include_tasks调用时,这个Play会因条件不满足自动跳过,直接执行后续任务列表。
修改后的task_update_dns.yml内容如下:
--- # 仅当直接运行本文件时触发该Play - name: Execute DNS update tasks hosts: "{{ ansible_limit | default('all') }}" tasks: # 导入当前文件的任务部分 - import_tasks: "{{ ansible_playbook_name }}" # 条件判断:当前执行的剧本名等于本文件名时生效 when: ansible_playbook_basename == ansible_playbook_name # 原有的任务列表,供include_tasks调用或被上面的Play导入 - name: dig mydomain.com set_fact: my_hosts: '{{ lookup("dig", "mydomain.com").split(",") }}' tags: always - name: Set entries blockinfile: ....
修改后,你既可以继续用include_tasks在其他剧本中调用它,也可以直接用ansible-playbook playbooks/task_update_dns.yml --limit $myserver独立运行。
方法二:用ansible命令直接调用任务文件
无需修改任务文件,直接使用ansible命令结合include_tasks模块运行单个任务文件,命令格式如下:
ansible $myserver -i <你的清单文件路径> -m include_tasks -a "file=playbooks/task_update_dns.yml"
这种方式绕过了剧本格式限制,直接在目标主机上执行任务文件中的内容。
内容的提问来源于stack exchange,提问作者Ricky Levi
相关产品推荐
相关产品推荐

