在 ansible playbook 中应使用 delegate_to: localhost 执行本地动作,适用于生成报告、调用本地脚本等场景;它比旧式 local_action 更清晰,需注意变量作用域、路径解析及权限配置。

在 Ansible Playbook 中执行本地动作,是指让任务在控制节点(即运行 ansible-playbook 的机器)上运行,而不是在远程目标主机上执行。这适用于生成报告、调用本地脚本、写入本地文件、触发 CI/CD 流程等场景。
什么时候该用 local_action?
当操作不需要或不应该在目标主机上进行时,比如:
- 把收集到的主机信息保存为本地 JSON 或 CSV 报告
- 用本地 Python 脚本处理变量或模板输出
- 向本地监控系统推送事件(如发送 Slack 通知)
- 在部署前校验本地配置文件语法是否正确
两种主流写法:local_action 和 delegate_to
两者功能高度重合,但推荐优先使用 delegate_to: localhost,因为更清晰、更符合现代 Ansible 实践。
-
local_action是旧式写法,语法略紧凑但可读性弱,例如:local_action: copy content="{{ inventory_hostname }}" dest=/tmp/host.txt -
delegate_to: localhost是显式委托,配合run_once: true可避免在多台主机上重复执行,例如:
- name: 生成单份汇总报告
copy:
content: "{{ hostvars | to_nice_json }}"
dest: "/tmp/inventory_summary.json"
delegate_to: localhost
run_once: true
关键注意事项
-
变量作用域不同:在
delegate_to: localhost的 task 中,{{ ansible_hostname }}指的是控制节点主机名,而{{ inventory_hostname }}仍指向当前遍历的目标主机(除非你明确用了hostvars) -
不自动跳过未连接主机:即使某台目标主机失联,只要 play 未中断,
delegate_to: localhost仍会执行——适合做兜底日志或告警 -
不能直接用
become提权到 root(若控制节点非 root):需确保控制节点当前用户有对应权限,或改用become_user: root并配置好 sudo 免密 -
路径是控制节点的路径:
src、dest、cmd等参数中的路径全部解析为控制节点上的路径
一个实用例子:批量收集后本地归档
以下 task 收集所有主机的 IP 和系统类型,并统一写入控制节点的 /tmp/inventory-report.yaml:
- name: 收集所有主机 facts
setup:
filter: "ansible_all_ipv4_addresses,ansible_distribution,ansible_architecture"
gather_facts: true
- name: 本地生成汇总 YAML 报告
copy:
content: |
{% for host in groups['all'] %}
{{ host }}:
ip: {{ hostvars[host].ansible_all_ipv4_addresses | first }}
os: {{ hostvars[host].ansible_distribution }} {{ hostvars[host].ansible_distribution_version }}
{% endfor %}
dest: "/tmp/inventory-report.yaml"
delegate_to: localhost
run_once: true











