1. 概述
Ansible 是一个强大的自动化工具,主要用于在远程主机上执行任务。但在某些场景下,我们也需要在 Ansible 控制器(即运行 Ansible 的主机)上执行命令。
通常,我们称这台机器为 localhost。本文将介绍几种在 Ansible 控制器上执行命令的方法。要完成本教程,建议先搭建一个基础实验环境。
2. 本地执行命令的典型用途
在 Ansible 控制器上执行命令有多种常见用途,例如:
- 创建目录用于备份
- 下载配置模板
- 执行本地 shell 脚本,比如部署前的准备脚本
这些只是常见场景,实际使用中还可能根据需求扩展。
3. 在本地执行命令的方式
Ansible 提供了多种方式直接在控制器主机上执行命令:
- 使用
connection
关键字 - 使用
local_action
模块 - 使用
delegate_to
关键字 - 使用 Ansible ad-hoc 命令
- 使用 Ansible Inventory 配置
接下来我们逐一介绍这些方法。
4. 使用 connection
插件
Ansible 提供了多种 connection 插件,其中一种是 ansible.builtin.local
,简称 local
。这个插件允许在控制器上执行任务,且无需建立 SSH 连接,因此执行速度较快。
4.1. 在 Playbook 中配置连接方式
我们可以在 Playbook 中通过 connection: local
指定使用本地连接,可以作用于整个 Playbook,也可以作用于单个 Task。
以下是一个获取系统 uptime
的 Playbook 示例:
---
- name: 获取系统运行时间
hosts: localhost
connection: local
tasks:
- name: 打印 uptime
command: uptime
register: "output"
- debug: var=output.stdout
执行这个 Playbook 会输出控制器的系统运行时间:
$ ansible-playbook connection.yaml
...
TASK [debug] *************************************************
ok: [localhost] => {
"output.stdout": " 07:06:39 up 16 min, 1 user, load average: 0.19, 0.06, 0.03"
}
...
4.2. 通过命令行指定连接方式
也可以不在 Playbook 中写 connection: local
,而是通过命令行参数 --connection=local
来指定:
$ ansible-playbook connection.yaml --connection=local
这样也能实现本地执行的效果,输出内容与上面一致。
⚠️ 注意:如果不指定 inventory 文件,Ansible 会提示 provided hosts list is empty
的警告。可以通过添加 inventory 文件来避免这个问题。
5. 使用 Ansible Inventory 文件
我们可以通过 Inventory 文件定义 localhost
的别名,从而在 Playbook 中引用。
例如,创建一个 inventory.ini
文件:
controller ansible_connection=local
然后修改 Playbook:
---
- name: 获取系统运行时间
hosts: controller
tasks:
- name: 打印 uptime
command: uptime
register: "output"
- debug: var=output.stdout
执行时带上 inventory 文件:
$ ansible-playbook inventory_demo.yaml -i inventory.ini
这样就能在控制器上执行命令,并避免警告信息。
6. 使用 delegate_to
关键字
delegate_to
用于将任务委托给特定主机执行,包括控制器本身。这在需要从多个主机上下文中执行本地操作时非常有用。
例如,从所有主机中复制文件到控制器:
---
- name: 将文件复制到本地
hosts: all
tasks:
- name: 本地复制文件
copy:
src: /home/vagrant/abc.txt
dest: /home/vagrant/ansible/
delegate_to: localhost
register: copy_result
- name: 显示复制结果
debug:
var: copy_result
执行后,只有控制器上完成了文件复制,其他主机跳过该任务。
7. 使用 local_action
模块
local_action
是 delegate_to: localhost
的简化写法,更简洁明了。
以下是一个使用 local_action
的 Playbook 示例:
---
- name: 使用 local_action 复制文件
hosts: all
tasks:
- name: 打印 uptime
command: uptime
register: "uptime_result"
- debug: var=uptime_result.stdout
- name: 本地复制文件
local_action: copy src=/home/vagrant/abc.txt dest=/home/vagrant/ansible/
register: "copy_result"
- name: 显示复制结果
debug:
var: copy_result
when: inventory_hostname == 'localhost'
执行后,uptime
会在所有主机上运行,但复制操作只在控制器上执行。
8. 使用 Ansible Ad-hoc 命令
Ansible 也支持通过 ad-hoc 命令在控制器上执行操作。
例如,使用 shell
模块打印信息:
$ ansible localhost -c local -m shell -a 'echo abc abc'
localhost | CHANGED | rc=0 >>
abc abc
也可以使用 IP 地址:
$ ansible 127.0.0.1 -c local -m shell -a 'echo abc abc'
127.0.0.1 | CHANGED | rc=0 >> abc abc
如果在 inventory 文件中将 127.0.0.1
定义为 controller
,也可以这样执行:
$ ansible controller -c local -m shell -a 'echo abc abc' -i inventory.ini
✅ 小贴士:使用 ad-hoc 命令时,-i
参数用于指定 inventory 文件。
9. 总结
本文介绍了在 Ansible 控制器上执行命令的多种方式:
方法 | 说明 |
---|---|
connection: local |
在 Playbook 中指定本地连接方式 |
local_action |
简化本地执行命令的写法 |
delegate_to |
将任务委托给本地执行,适用于多主机场景 |
Ansible Inventory | 通过 inventory 文件定义本地主机 |
Ad-hoc 命令 | 快速执行本地命令 |
通过这些方法,你可以灵活地在 Ansible Playbook 或命令行中控制本地和远程任务的执行,提高自动化效率。