适合读者:已经掌握基础 Linux 命令,想把重复操作变成可复用配置的初级运维人员。本文先管理本机的一个练习文件,再解释怎样迁移到 SSH 主机。

1. 从一次“重复创建文件”理解 Ansible
假设需要在几台机器上放一份统一说明文件。手工做法是逐台登录、编辑文件、设置权限,再检查有没有漏机器。Ansible 把主机清单和目标状态写下来,让控制端按任务执行。
先认识三个词:Inventory 说明管理哪些机器;Module 提供复制文件、创建目录等具体能力;Playbook 用 YAML 把目标主机和一组任务组织起来。
本次只使用 Ansible 内置模块,不需要额外安装第三方集合。控制端使用已安装 ansible-core 的 Linux 或合适的 WSL 环境,Python 和 Ansible 的版本要求以所安装版本的文档为准。可以从 Ansible 官方安装说明 选择安装方式。
ansible --version
ansible-playbook --version
command -v python3
2. 写一份只包含本机的 Inventory
创建工作目录并进入:
mkdir -p "$HOME/ansible-lab"
cd "$HOME/ansible-lab"
使用编辑器保存 inventory.ini:
[lab]
local-demo ansible_connection=local ansible_python_interpreter=/usr/bin/python3
lab 是主机组,local-demo 是清单里的主机别名。ansible_connection=local 明确选择本地执行,不通过 SSH;Python 路径需要与前面的查询结果一致。
先确认清单解析结果和实际目标:
ansible-inventory -i inventory.ini --graph
ansible lab -i inventory.ini --list-hosts
预期只有 local-demo。这一步能避免“任务写得对,却跑到了错误机器上”。Inventory 的组和主机组织方式见 官方入门指南。
3. Ansible 的 ping 和系统 ping 检查的不是同一件事
ansible lab -i inventory.ini -m ansible.builtin.ping
预期得到 SUCCESS 和 pong。ansible.builtin.ping 用于验证 Ansible 连接方式及可用 Python,不是 ICMP 探测。由于本例使用 local 连接,它也没有验证任何远程 SSH 链路。模块行为见 ping 官方文档。
能得到 pong 后,再开始写会改变文件的任务,这样连接问题和任务问题可以分开定位。
4. 写第一个 Playbook:声明文件应当是什么样
使用编辑器保存 notice.yml:
---
- name: Manage a learning notice file
hosts: lab
gather_facts: true
become: false
vars:
notice_path: "{{ ansible_facts['user_dir'] }}/ansible-lab-notice.txt"
tasks:
- name: Ensure the notice has the expected content and mode
ansible.builtin.copy:
dest: "{{ notice_path }}"
mode: '0640'
content: |
managed_by=ansible
environment=lab
- name: Show the managed file location
ansible.builtin.debug:
msg: "Managed file: {{ notice_path }}"
这里将文件放在执行用户的家目录中,父目录已经存在,不需要提权。练习前确认 ansible-lab-notice.txt 不是自己已有的重要文件。
copy 的目标不是“每次都执行一次复制动作”,而是确保内容与权限符合要求。mode 用带引号的字符串,避免 YAML 数字解释造成歧义。具体参数见 copy 模块文档。
5. 先检查目标,再预览差异
ansible-playbook -i inventory.ini notice.yml --syntax-check
ansible-playbook -i inventory.ini notice.yml --list-hosts
ansible-playbook -i inventory.ini notice.yml \
--limit local-demo --check --diff
三次检查分别回答:语法是否可读取、目标主机是谁、模块预计会修改什么。--limit 给本次执行再加一道目标限制。
本例的 copy 模块支持 check mode,因此新文件尚不存在时,预览通常会报告预计变更,而不创建文件。预览不是完整执行:某些模块不支持它;如果后续任务依赖前序任务实际创建的目录或结果,预览也可能失败。不能把“预览通过”视作所有运行条件都已验证。详见 check mode 和 diff mode 文档。
--diff 会显示内容差异,处理密码或令牌时不要随意输出;本例文件只有教学文字。
6. 执行两遍,观察幂等性
正式执行并查看结果:
ansible-playbook -i inventory.ini notice.yml --limit local-demo
cat "$HOME/ansible-lab-notice.txt"
stat -c '%a %n' "$HOME/ansible-lab-notice.txt"
预期内容为两行设置,权限为 640。再原样执行一次:
ansible-playbook -i inventory.ini notice.yml --limit local-demo
如果文件与权限没有被其他程序改变,第二次的回顾应显示 changed=0、failed=0。这就是本例的幂等效果:目标状态已经满足时,再执行不会产生新的修改。
如果手动把文件内容改掉,再执行 Playbook,copy 任务会重新把它恢复为声明的内容。这也说明:将某个文件交给 Ansible 管理后,临时手工修改可能在下一次执行时被覆盖。
并不是任意 Playbook 都天然幂等。随意使用 shell 或 command 执行“追加一行”,往往每次都会改变结果。能使用表达目标状态的模块时,应优先使用对应模块。
7. 迁移到远程 SSH 主机时,新增了哪些条件
下面是远程清单示意,文档地址必须替换成真实测试机:
[web]
web01 ansible_host=192.0.2.20 ansible_user=ops ansible_python_interpreter=/usr/bin/python3
先使用正常 SSH 流程核对主机身份、用户和认证,再测试:
ansible web -i inventory.ini --list-hosts
ansible web -i inventory.ini --limit web01 -m ansible.builtin.ping
这里的 web 组与前面 Playbook 的 hosts: lab 不同。以后要把该 Playbook 用于远程练习,应先明确调整 hosts,再复查目标,不能只换 Inventory 就以为目标已自动迁移。
远程 Linux 主机通常还要有适配模块的 Python。需要管理员权限的任务,再按实际需求配置 become;这个普通文件练习没有开启它。
不要为省事直接关闭 SSH 主机密钥检查。出现密钥变化时,核对是否重装或连接到了其他机器,再更新可信记录。相关机制见 Ansible 连接说明。
8. 新手常见报错该看哪一层
| 报错或现象 | 优先检查 |
|---|---|
No hosts matched |
清单路径、组名、hosts 和 limit 是否有交集 |
UNREACHABLE |
SSH 地址、端口、用户、认证和连接插件 |
| 找不到 Python | 目标端实际解释器位置和模块支持要求 |
FAILED 且 Permission denied |
哪个文件、哪个用户、是否需要提权 |
| YAML 解析失败 | 缩进、冒号、引号;YAML 缩进使用空格 |
每次都 changed |
任务是否重复追加、动态内容是否一直变化 |
第一份自动化的目标可以很小:清单只指向一台测试机,任务只管理一个文件,执行前看目标和差异,执行后检查实际内容,再重复执行确认结果稳定。这个闭环跑顺后,再扩展到服务配置和批量发布更容易掌控。