Ansible 自动化运维速查表 - Ansible 常用命令与模块大全
Ansible 的核心特征是不在被管机器上装任何 agent,全部经 SSH 执行,这决定了它的适用边界:能 SSH 就能管,跨云、跨机房、跨临时容器都一样。第二个特征是模块的幂等性——同一个任务跑第二遍应该什么都不做,这是它能被反复执行而不搞坏系统的前提,也是它与 shell 脚本批量执行的根本区别(后者不做状态判断,第二遍往往出事)。这张表按核心命令、ad-hoc、常用模块、Playbook 结构、变量与模板、Inventory 管理、角色与最佳实践七组铺开。什么时候该翻它:从 ad-hoc 单条命令试探连通性,确认能连再写成 Playbook;改动前先 --check 预演或 --syntax-check 只验语法。角色化是团队协作的分水岭:变量放 defaults、可复用任务放 roles、敏感值放 ansible-vault。
典型使用场景
面向一次要改动几十上百台同构机器、又不能接受「脚本里藏着一台漏配」的运维工程师。Ansible 的核心不是 SSH 批量执行,而是幂等:同一份 playbook 跑第二遍不应该产生额外变更,所以应该优先用模块(apt / copy / template / service / user / file / git)而不是 shell;只有在模块表达不了时才退到 shell,并且给它加 creates / removes 判断。本表覆盖 ad-hoc 命令(ansible + -m -a)、常用模块与参数、playbook 结构(hosts / become / pre_tasks / handlers / roles)、变量与模板(vars_files / when / register / with_items)、inventory 管理(分组、组嵌套、主机变量、动态 inventory)以及 ansible-galaxy 与 role 目录规范。适合在写第一条幂等任务前对照检查一遍「这条命令跑第二遍会怎样」。
核心命令 6
ansible all -m pingansible-playbook site.ymlansible-galaxy init myroleansible-galaxy install geerlingguy.nginxansible-vault encrypt secrets.ymlansible-doc -l | grep copyad-hoc 命令 7
ansible webservers -m shell -a "uptime"ansible all -m setup -a "filter=ansible_os_family"ansible all -m copy -a "src=file.txt dest=/tmp/"ansible all -m service -a "name=nginx state=started"ansible webservers -m yum -a "name=nginx state=latest"ansible all -m ping --limit web1ansible all -m shell -a "df -h" -f 10常用模块 7
- name: Install nginx
apt:
name: nginx
state: present- name: Copy config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf- name: Start service
service:
name: nginx
state: started
enabled: yes- name: Create user
user:
name: deploy
shell: /bin/bash- name: Run command
shell: npm run build
args:
chdir: /app- name: Create dir
file:
path: /opt/app
state: directory
mode: "0755"- name: Git clone
git:
repo: https://github.com/x/y.git
dest: /srv/appPlaybook 结构 6
- hosts: webservers
become: yes
tasks: [...]pre_tasks: / post_tasks:handlers:
- name: restart nginx
service: name=nginx state=restartedvars:
nginx_port: 80- name: notify handler
template: ...
notify: restart nginx- import_playbook: db.yml变量与模板 6
vars_files:
- vars/secrets.yml- command: ...
when: ansible_os_family == "Debian"- user: name={{ item }}
with_items:
- alice
- bob- command: ...
register: result{{ nginx_port }} / {{ ansible_hostname }}when: result.rc == 0Inventory 管理 5
[webservers]
web1 ansible_host=10.0.1.1
web2 ansible_host=10.0.1.2[web:children]
web1
web2ansible all -i hosts.yml --list-hostsansible all -i ec2.py --list-hostsweb1 ansible_host=10.0.1.1 ansible_user=deploy ansible_port=2222角色与最佳实践 5
ansible-galaxy init myroleroles/myrole/{tasks,handlers,templates,files,defaults,vars}/main.yml- hosts: web
roles:
- nginx
- { role: db, when: enable_db }- import_role:
name: nginx
tags: setup[defaults]
inventory = hosts
remote_user = deploy
host_key_checking = False参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
ansible all -m ping | ad-hoc 模式跑 ping 模块,验证连通性与 Python 可用性,是任何操作前的第一步 | ansible all -m ping |
ansible webservers -m shell -a "uptime" | 在 webservers 组内执行命令;shell 不幂等,重跑就会再执行一次 | ansible webservers -m shell -a "uptime" |
ansible all -m setup -a "filter=ansible_os_family" | 采集事实并按 filter 只取需要的字段,比全量 setup 输出可读得多 | ansible all -m setup -a "filter=ansible_os_family" |
ansible all -m copy -a "src=file.txt dest=/tmp/" | 幂等拷贝;文件内容相同则 reported changed 为 false | ansible all -m copy -a "src=file.txt dest=/tmp/" |
ansible all -m service -a "name=nginx state=started" | 声明服务处于 running 状态;已经是 running 就不会重启 | ansible all -m service -a "name=nginx state=started" |
ansible all -m ping --limit web1 | 把作用范围收敛到单台主机,是分批灰度与排障时的关键开关 | ansible all -m ping --limit web1 |
ansible all -m shell -a "df -h" -f 10 | -f 指定并发数;默认 5 并发,几百台机器时并发太低调高效率也容易打满控制端 | ansible all -m shell -a "df -h" -f 10 |
ansible-playbook site.yml | 执行 playbook,是所有正式变更的唯一入口 | ansible-playbook site.yml |
ansible-galaxy init myrole | 生成符合官方约定的角色骨架(tasks/handlers/templates/files/defaults/vars) | ansible-galaxy init myrole |
ansible-galaxy install geerlingguy.nginx | 从 Galaxy 安装第三方角色;执行前应固定版本,否则升级会引入未预期变更 | ansible-galaxy install geerlingguy.nginx |
ansible-vault encrypt secrets.yml | 加密敏感变量文件,解密需要 vault 密码,密码本身不要放进仓库 | ansible-vault encrypt secrets.yml |
ansible-doc -l | grep copy | 查模块清单与文档,参数记不清时用它比搜索引擎更准 | ansible-doc -l | grep copy |
apt: name=nginx state=present | 声明包处于已安装状态,比 command + dpkg 幂等得多 | - name: Install nginx
apt:
name: nginx
state: present |
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf | 用 Jinja2 模板下发配置,模板变化才会触发实际写入 | - name: Copy config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf |
service: name=nginx state=restarted enabled=yes | 重启服务并设置开机自启;state=restarted 是无条件重启,需配合 handler 才合理 | - name: Start service
service:
name: nginx
state: started
enabled: yes |
shell: npm run build
args:
chdir: /app | 在指定目录执行命令;chdir 是必需的,否则会在控制端的当前目录跑 | - name: Run command
shell: npm run build
args:
chdir: /app |
file: path=/opt/app state=directory mode="0755" | 幂等创建目录与设置权限;mode 要写成字符串,否则 0755 会被当十进制解析 | - name: Create dir
file:
path: /opt/app
state: directory
mode: "0755" |
git: repo=... dest=/srv/app | 幂等拉取代码,可加 version 指定分支或 tag | - name: Git clone
git:
repo: https://github.com/x/y.git
dest: /srv/app |
hosts: webservers + become: yes | 任务作用范围与提权开关;become 是最常见的权限坑来源 | - hosts: webservers
become: yes
tasks: [...] |
pre_tasks: / post_tasks: | 把动作插在 roles 前后,用来做前置断言与收尾校验 | pre_tasks: / post_tasks: |
handlers + notify | 任务变更时才触发一次收尾动作;用 notify 而不是直接写重启可避免配置没变也重启 | - name: notify handler
template: ...
notify: restart nginx |
import_playbook: db.yml | 把 playbook 拆分后复用,避免一个巨型 playbook 失控 | - import_playbook: db.yml |
vars_files: - vars/secrets.yml | 注入变量文件,与 inventory 的 group_vars/host_vars 共同构成优先级链 | vars_files:
- vars/secrets.yml |
when: ansible_os_family == "Debian" | 条件执行,跨发行版 playbook 靠它分流包管理器与服务名 | - command: ...
when: ansible_os_family == "Debian" |
register: result + when: result.rc == 0 | 捕获前一步结果再做判断,是把非幂等命令包成幂等的常用手段 | - command: ...
register: result |
with_items: | 对列表逐项展开任务,比写 N 条重复任务更容易维护 | - user: name={{ item }}
with_items:
- alice
- bob |
[web:children] | 组的嵌套,让 web 组自动包含 child 组,删掉主机会自动从组里消失 | [web:children]
web1
web2 |
ansible all -i hosts.yml --list-hosts | 只解析 inventory 并列出目标主机,不执行任何任务,是排 inventory 问题的第一步 | ansible all -i hosts.yml --list-hosts |
web1 ansible_host=10.0.1.1 ansible_user=deploy ansible_port=2222 | 主机级变量;连不上时几乎总是这里的三项之一配错 | web1 ansible_host=10.0.1.1 ansible_user=deploy ansible_port=2222 |
roles/myrole/{tasks,handlers,templates,files,defaults,vars}/main.yml | 官方约定的角色目录结构,defaults 放可覆盖默认值、vars 放内部变量 | roles/myrole/{tasks,handlers,templates,files,defaults,vars}/main.yml |
- { role: db, when: enable_db } | 在 roles 列表里给单个角色加条件,实现「按开关启用一组任务」 | - hosts: web
roles:
- nginx
- { role: db, when: enable_db } |
tags: setup | 打标签后可用 --tags 只跑一部分,是大 playbook 的必备逃生阀 | - import_role:
name: nginx
tags: setup |
[defaults]
inventory = hosts | ansible.cfg 默认段,集中管理 inventory 路径与 host_key_checking 等行为 | [defaults]
inventory = hosts
remote_user = deploy
host_key_checking = False |
易错点与避坑指南
现象模板已经修改了配置,但服务没有重启,变更看起来没生效。
原因重启被写在任务里而不是 handler 里,或者模板内容实际没变化导致任务 reported changed=false。
处置把重启写成 handler 并用 notify 触发;先确认任务输出里确实出现 changed,再用 --check --diff 预演模板差异。
现象任务报 "command not found" 或找不到 node / npm,终端里同样的命令正常。
原因非交互 shell 没加载 nvm / pyenv 的环境,PATH 里没有这些目录。
处置在任务里用 command 加 chdir 与 environment,或先执行 profile 脚本;不要指望 login shell 的 rc 生效。
现象首次运行成功,第二次运行依然报大量 changed,幂等性失效。
原因用了 shell / command 模块且缺少 creates / removes 之类的判断条件,任务本身不幂等。
处置优先换成对应模块(file / copy / service / user);确实只能用 command 时加 creates 或先用 stat 注册结果再 when 跳过。
现象mode: 0755 权限设错,实际变成了 0755 之外的奇怪值或被当成十进制 755。
原因YAML 会把 0755 解析成八进制或十进制,取决于写法与解析器行为,字符串更安全。
处置把 mode 写成字符串 "0755",需要运算时用 mode: "{{ 0o755 | int }}" 明确转换。
现象变量明明在 group_vars 里写了,模板里却是空的。
原因优先级链顺序被忽略:命令行 > role defaults > inventory group_vars/host_vars > role vars,变量名写错层级也看不出来。
处置用 ansible all -m debug -a "var=nginx_port" 在目标主机上确认实际生效值,再核对变量名拼写。
现象playbook 卡在某台主机上不动,后面所有任务都被拖住。
原因默认 ssh 连接会长时间等待超时,且 host 数量多时没有并发上限。
处置给 SSH 配置加 ConnectTimeout 与 ssh_args 的 ControlMaster 复用,playbook 里用 -f 限制并发并用 serial 分批。
现象运行时报 "MODULE FAILURE" 或 skipped 掉一批主机。
原因目标主机没有 Python 解释器(老旧发行版常见),或远端 Python 版本不满足要求。
处置先 ansible all -m ping 确认连通性;对无 Python 的机器用 raw 模块做最小引导后再切回正常模块。
现象galaxy 装完角色能跑,但换台机器就失败。
原因role 依赖未写进 requirements.yml,且默认装的是最新版本,行为随上游漂移。
处置把角色依赖与版本固定进 requirements.yml,部署流程里先跑 galaxy install 再跑 playbook。
排障路径
1只解析 inventory,确认目标主机列表
ansible all -i hosts.yml --list-hosts列表不对时后面所有任务都白搭,先把主机范围对。
2验证连通性与远端 Python
ansible all -m pingping 失败先解决 SSH、become 与 Python,而不是继续跑任务。
3只看目标主机的关键事实字段
ansible all -m setup -a "filter=ansible_os_family"确认发行版族,跨发行版的条件分支依赖它。
4预演变更,不实际落地
ansible-playbook site.yml --check --diff--check 只预测,--diff 显示文件差异,是上线前最该跑的一步。
5限制到单台主机排查
ansible-playbook site.yml --limit web1缩小爆炸半径,同时 -vvv 看完整输出。
6查看某个模块的完整参数说明
ansible-doc -l | grep copy参数记不清时以模块文档为准,不要凭记忆拼参数。
命令示例
先做连通性自检再动生产
ansible all -i hosts.yml --list-hosts
ansible all -m ping--list-hosts 先确认匹配到哪些主机,避免组名写错把任务打到意外的范围。ping 验证 SSH 与 Python 依赖是否就绪。
输出
hosts (4):
web1
web2
db1
db2
web1 | SUCCESS => {
"changed": false,
"ping": "pong"
}带模板渲染部署配置,变更才重启服务
- name: Render nginx.conf
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service: name=nginx state=restartedhandler 只在任务 report changed 时触发,配置没变就不重启服务,避免无意义的连接中断。这是 handler 最主要的用途。
用 --check 空跑预演
ansible-playbook site.yml --check --diff--check 不真正执行,--diff 显示将发生的变更。上生产前用它确认影响面,尤其配合限制目标 --limit web1。
输出
TASK [Gathering Facts] ************************************* TASK [template : Render nginx.conf] ************************ --- before +++ after @@ -1 +1 @@ -worker_processes auto; +worker_processes 4;
常见坑与注意事项
- ad-hoc 的 -m shell 不保证幂等,重复执行可能产生副作用;会重复执行的操作应写成 Playbook 改用幂等模块。
- handlers 在 play 末尾统一执行,不在触发它的那一步之后立刻执行,需要即时生效要改用普通任务。
- 主机组名写错会静默匹配不到目标主机,先用 --list-hosts 确认匹配结果再执行。
- 模板渲染失败(如 Jinja2 变量未定义)会中断任务,敏感变量用 ansible-vault 加密而非明文写入。
- 在循环里注册变量时 register 会累积成列表,直接引用会拿到最后一次而非全部结果。
提示
- Ansible 默认使用 SSH 连接,无需在目标机器安装 Agent。
- template 模块用 Jinja2 语法渲染配置文件,比 copy 更灵活。
- --check 模式(dry-run)可以预览 Playbook 执行效果而不实际修改系统。
- roles 目录结构:tasks/main.yml、handlers/main.yml、templates/、files/、defaults/main.yml。
- 敏感数据用 ansible-vault 加密,配合 vars_files 引入,不要硬编码进 Playbook。
- group_vars/ 和 host_vars/ 目录可按组和主机自动加载变量,比内联更易维护。
ansible all -m ping是连通性自检,playbook 报错时先跑它区分是网络问题还是语法问题。ansible-doc -l | grep copy查模块参数与示例,比搜博客准确且带用例。become: yes写在 play 级是全量提权,只要个别任务提权就单独标在 task 上。
常见问题
handler 什么时候会被触发?
handler 只在被 notify 的任务真正发生了变更时才执行一次,且在所有普通任务跑完之后统一执行。这是它和普通任务的本质区别:普通任务每次都跑,handler 是「有变化才跑」。所以配置模板没变时不会重启服务,避免无意义的服务抖动。若需要每次都执行,就别用 handler,直接写普通任务。
ad-hoc 命令和 Playbook 该怎么选?
ad-hoc 适合一次性操作和临时排查,比如 ansible webservers -m shell -a "uptime" 快速确认状态。Playbook 适合需要重复执行、可版本控制、有复杂逻辑的任务,因为它能被 code review、能用 --check 做空跑预演。建议:任何会重复执行的操作都应该写成 Playbook。
什么是幂等性,Ansible 的模块为什么强调它?
幂等指同一个操作执行多次和执行一次的结果相同。用 copy 模块部署配置时,源文件没变就不会传输,保持 mtime 不变;用 service 模块管理服务时,state=started 表示「确保它在运行」,已经运行则不做任何事。优先用这些专用模块而不是 shell,能自动获得幂等性,也避免了手写命令判断状态的麻烦。
如何让任务只在特定条件下执行?
用 when 字段配合 Jinja2 表达式,例如 when: ansible_os_family == "Debian",这样只在 Debian 系主机上跑。需要复用条件时把表达式抽成变量更清晰。循环用 with_items 遍历列表,- user: name={{ item }} 配合 with_items 会为每个元素执行一次任务。
敏感数据怎么处理?
用 ansible-vault encrypt secrets.yml 把敏感变量文件加密,再在 vars_files 里引用。模板渲染用 template 模块配合 Jinja2 的 {{ nginx_port }} 引用变量,比自己拼字符串更安全可维护。连接参数如 host_key_checking 可以在 ansible.cfg 里统一配置,避免散落在各处。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。