Ansible 自动化运维速查表 - Ansible 常用命令与模块大全

Ansible 的核心特征是不在被管机器上装任何 agent,全部经 SSH 执行,这决定了它的适用边界:能 SSH 就能管,跨云、跨机房、跨临时容器都一样。第二个特征是模块的幂等性——同一个任务跑第二遍应该什么都不做,这是它能被反复执行而不搞坏系统的前提,也是它与 shell 脚本批量执行的根本区别(后者不做状态判断,第二遍往往出事)。这张表按核心命令、ad-hoc、常用模块、Playbook 结构、变量与模板、Inventory 管理、角色与最佳实践七组铺开。什么时候该翻它:从 ad-hoc 单条命令试探连通性,确认能连再写成 Playbook;改动前先 --check 预演或 --syntax-check 只验语法。角色化是团队协作的分水岭:变量放 defaults、可复用任务放 roles、敏感值放 ansible-vault。

系统与运维·共 42 条命令·最后更新 2026-07-21
ansible自动化运维devops

典型使用场景

面向一次要改动几十上百台同构机器、又不能接受「脚本里藏着一台漏配」的运维工程师。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 ping
测试所有主机连通性
ansible-playbook site.yml
执行 Playbook
ansible-galaxy init myrole
初始化角色目录结构
ansible-galaxy install geerlingguy.nginx
从 Galaxy 安装角色
ansible-vault encrypt secrets.yml
加密敏感变量文件
ansible-doc -l | grep copy
列出模块并搜索用法

ad-hoc 命令 7

ansible webservers -m shell -a "uptime"
在指定组执行 shell 命令
ansible all -m setup -a "filter=ansible_os_family"
收集主机 facts 信息
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 web1
只对匹配的主机执行
ansible all -m shell -a "df -h" -f 10
设置并行 fork 数量加速执行

常用模块 7

- name: Install nginx apt: name: nginx state: present
apt/yum 包管理模块
- name: Copy config template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf
template 模板渲染模块
- name: Start service service: name: nginx state: started enabled: yes
service 服务管理模块
- name: Create user user: name: deploy shell: /bin/bash
user 用户管理模块
- name: Run command shell: npm run build args: chdir: /app
shell 命令执行模块
- name: Create dir file: path: /opt/app state: directory mode: "0755"
file 文件/目录管理模块
- name: Git clone git: repo: https://github.com/x/y.git dest: /srv/app
git 代码检出模块

Playbook 结构 6

- hosts: webservers become: yes tasks: [...]
指定目标主机并启用 sudo
pre_tasks: / post_tasks:
在 roles 前后执行的任务
handlers: - name: restart nginx service: name=nginx state=restarted
定义 handler,被 notify 触发
vars: nginx_port: 80
在 Playbook 中内联变量
- name: notify handler template: ... notify: restart nginx
任务变更后通知 handler 执行
- import_playbook: db.yml
引入其他 Playbook

变量与模板 6

vars_files: - vars/secrets.yml
从文件加载变量
- command: ... when: ansible_os_family == "Debian"
条件执行,支持 Jinja2 表达式
- user: name={{ item }} with_items: - alice - bob
循环遍历列表
- command: ... register: result
将任务输出注册到变量
{{ nginx_port }} / {{ ansible_hostname }}
Jinja2 模板语法引用变量
when: result.rc == 0
基于上一任务返回值做条件判断

Inventory 管理 5

[webservers] web1 ansible_host=10.0.1.1 web2 ansible_host=10.0.1.2
INI 格式 Inventory
[web:children] web1 web2
定义组嵌套关系
ansible all -i hosts.yml --list-hosts
指定 Inventory 并列出匹配主机
ansible all -i ec2.py --list-hosts
使用动态 Inventory(云平台)
web1 ansible_host=10.0.1.1 ansible_user=deploy ansible_port=2222
为主机指定连接参数

角色与最佳实践 5

ansible-galaxy init myrole
生成标准角色目录结构
roles/myrole/{tasks,handlers,templates,files,defaults,vars}/main.yml
角色标准目录约定
- hosts: web roles: - nginx - { role: db, when: enable_db }
在 Playbook 中使用角色
- import_role: name: nginx tags: setup
静态引入角色并打标签
[defaults] inventory = hosts remote_user = deploy host_key_checking = False
ansible.cfg 全局配置

参数矩阵

参数作用示例
ansible all -m pingad-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 为 falseansible 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 = hostsansible.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. 1只解析 inventory,确认目标主机列表

    ansible all -i hosts.yml --list-hosts

    列表不对时后面所有任务都白搭,先把主机范围对。

  2. 2验证连通性与远端 Python

    ansible all -m ping

    ping 失败先解决 SSH、become 与 Python,而不是继续跑任务。

  3. 3只看目标主机的关键事实字段

    ansible all -m setup -a "filter=ansible_os_family"

    确认发行版族,跨发行版的条件分支依赖它。

  4. 4预演变更,不实际落地

    ansible-playbook site.yml --check --diff

    --check 只预测,--diff 显示文件差异,是上线前最该跑的一步。

  5. 5限制到单台主机排查

    ansible-playbook site.yml --limit web1

    缩小爆炸半径,同时 -vvv 看完整输出。

  6. 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=restarted

handler 只在任务 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日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们