Ansible Ad-hoc 命令 #

什么是 Ad-hoc 命令? #

Ad-hoc 命令是 Ansible 提供的一种快速执行临时任务的方式,无需编写 Playbook,直接在命令行执行单个任务。

text
┌─────────────────────────────────────────────────────────────┐
│                   Ad-hoc vs Playbook                         │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  Ad-hoc 命令              Playbook                          │
│  ────────────            ──────────                         │
│  单行命令                YAML 文件                           │
│  临时任务                可重复任务                          │
│  快速执行                复杂编排                            │
│  无需保存                版本控制                            │
│  简单操作                复杂逻辑                            │
│                                                              │
└─────────────────────────────────────────────────────────────┘

基本语法 #

命令格式 #

bash
ansible <pattern> -m <module> -a "<arguments>" [options]

参数说明 #

参数 说明
pattern 主机模式,指定目标主机
-m 指定模块名称
-a 模块参数
-i 指定清单文件
-u 指定连接用户
-b 使用提权(become)
–become-user 提权用户
-v 详细输出
-f 并发数

常用模块示例 #

ping 模块 #

测试主机连通性:

bash
# 测试所有主机
ansible all -m ping

# 测试特定组
ansible webservers -m ping

# 测试特定主机
ansible web1 -m ping

# 输出示例
web1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

command 模块 #

在远程主机执行命令(默认模块):

bash
# 执行简单命令
ansible all -a "uptime"

# 查看主机名
ansible all -a "hostname"

# 查看磁盘使用
ansible all -a "df -h"

# 查看内存使用
ansible all -a "free -m"

# 列出文件
ansible all -a "ls -la /tmp"

# 注意:command 模块不支持管道、重定向等 shell 特性
# 以下命令不会按预期工作
ansible all -a "cat /etc/passwd | grep root"  # 错误

shell 模块 #

执行 shell 命令,支持管道、重定向等:

bash
# 使用管道
ansible all -m shell -a "cat /etc/passwd | grep root"

# 使用重定向
ansible all -m shell -a "echo 'hello' > /tmp/hello.txt"

# 使用环境变量
ansible all -m shell -a "echo $HOME"

# 使用子 shell
ansible all -m shell -a "for i in {1..5}; do echo $i; done"

# 查看服务状态
ansible all -m shell -a "systemctl status nginx"

# 查看进程
ansible all -m shell -a "ps aux | grep nginx"

copy 模块 #

复制文件到远程主机:

bash
# 复制文件
ansible all -m copy -a "src=/local/file.txt dest=/tmp/file.txt"

# 复制并设置权限
ansible all -m copy -a "src=file.txt dest=/tmp/file.txt mode=0644"

# 复制并设置所有者
ansible all -m copy -a "src=file.txt dest=/tmp/file.txt owner=root group=root"

# 直接写入内容
ansible all -m copy -a "content='Hello Ansible' dest=/tmp/hello.txt"

# 备份原文件
ansible all -m copy -a "src=file.txt dest=/tmp/file.txt backup=yes"

# 创建目录
ansible all -m copy -a "src=files/ dest=/tmp/files/"

file 模块 #

管理文件和目录:

bash
# 创建目录
ansible all -m file -a "path=/tmp/mydir state=directory"

# 创建文件
ansible all -m file -a "path=/tmp/myfile state=touch"

# 删除文件
ansible all -m file -a "path=/tmp/myfile state=absent"

# 删除目录
ansible all -m file -a "path=/tmp/mydir state=absent"

# 修改权限
ansible all -m file -a "path=/tmp/file mode=0755"

# 修改所有者
ansible all -m file -a "path=/tmp/file owner=root group=root"

# 创建符号链接
ansible all -m file -a "src=/tmp/file dest=/tmp/link state=link"

# 递归修改目录权限
ansible all -m file -a "path=/tmp/mydir mode=0755 recurse=yes"

apt 模块 #

管理 Debian/Ubuntu 软件包:

bash
# 更新缓存
ansible all -m apt -a "update_cache=yes" -b

# 安装软件包
ansible all -m apt -a "name=nginx state=present" -b

# 安装多个软件包
ansible all -m apt -a "name=nginx,git,curl state=present" -b

# 安装指定版本
ansible all -m apt -a "name=nginx=1.18.0 state=present" -b

# 卸载软件包
ansible all -m apt -a "name=nginx state=absent" -b

# 更新所有软件包
ansible all -m apt -a "upgrade=dist" -b

# 安装 deb 包
ansible all -m apt -a "deb=/tmp/package.deb" -b

yum 模块 #

管理 RHEL/CentOS 软件包:

bash
# 安装软件包
ansible all -m yum -a "name=nginx state=present" -b

# 安装多个软件包
ansible all -m yum -a "name=nginx,git,curl state=present" -b

# 安装指定版本
ansible all -m yum -a "name=nginx-1.18.0 state=present" -b

# 卸载软件包
ansible all -m yum -a "name=nginx state=absent" -b

# 更新所有软件包
ansible all -m yum -a "name=* state=latest" -b

# 从 URL 安装
ansible all -m yum -a "name=https://example.com/package.rpm state=present" -b

service 模块 #

管理服务:

bash
# 启动服务
ansible all -m service -a "name=nginx state=started" -b

# 停止服务
ansible all -m service -a "name=nginx state=stopped" -b

# 重启服务
ansible all -m service -a "name=nginx state=restarted" -b

# 重载配置
ansible all -m service -a "name=nginx state=reloaded" -b

# 开机启动
ansible all -m service -a "name=nginx enabled=yes" -b

# 禁用开机启动
ansible all -m service -a "name=nginx enabled=no" -b

# 启动并设置开机启动
ansible all -m service -a "name=nginx state=started enabled=yes" -b

user 模块 #

管理用户:

bash
# 创建用户
ansible all -m user -a "name=deploy" -b

# 创建用户并设置 shell
ansible all -m user -a "name=deploy shell=/bin/bash" -b

# 创建用户并设置密码
ansible all -m user -a "name=deploy password={{ 'mypassword' | password_hash('sha512') }}" -b

# 创建用户并添加到组
ansible all -m user -a "name=deploy groups=sudo append=yes" -b

# 创建系统用户
ansible all -m user -a "name=appuser system=yes" -b

# 创建用户并指定 home 目录
ansible all -m user -a "name=deploy home=/home/deploy create_home=yes" -b

# 删除用户
ansible all -m user -a "name=deploy state=absent" -b

# 删除用户及其 home 目录
ansible all -m user -a "name=deploy state=absent remove=yes" -b

# 生成 SSH 密钥
ansible all -m user -a "name=deploy generate_ssh_key=yes ssh_key_bits=2048" -b

group 模块 #

管理组:

bash
# 创建组
ansible all -m group -a "name=developers" -b

# 创建组并指定 GID
ansible all -m group -a "name=developers gid=1001" -b

# 创建系统组
ansible all -m group -a "name=appgroup system=yes" -b

# 删除组
ansible all -m group -a "name=developers state=absent" -b

git 模块 #

管理 Git 仓库:

bash
# 克隆仓库
ansible all -m git -a "repo=https://github.com/user/repo.git dest=/var/www/app"

# 克隆指定分支
ansible all -m git -a "repo=https://github.com/user/repo.git dest=/var/www/app version=develop"

# 克隆指定标签
ansible all -m git -a "repo=https://github.com/user/repo.git dest=/var/www/app version=v1.0.0"

# 更新仓库
ansible all -m git -a "repo=https://github.com/user/repo.git dest=/var/www/app update=yes"

# 强制更新
ansible all -m git -a "repo=https://github.com/user/repo.git dest=/var/www/app force=yes"

setup 模块 #

收集主机信息(Facts):

bash
# 收集所有 Facts
ansible all -m setup

# 过滤特定 Facts
ansible all -m setup -a "filter=ansible_eth*"

# 收集内存信息
ansible all -m setup -a "filter=ansible_mem*"

# 收集系统信息
ansible all -m setup -a "filter=ansible_distribution*"

# 收集网络信息
ansible all -m setup -a "filter=ansible_default_ipv4"

# 收集特定子集
ansible all -m setup -a "gather_subset=network"
ansible all -m setup -a "gather_subset=hardware"
ansible all -m setup -a "gather_subset=!all"

debug 模块 #

输出调试信息:

bash
# 输出消息
ansible localhost -m debug -a "msg='Hello Ansible'"

# 输出变量
ansible localhost -m debug -a "var=ansible_facts"

# 输出多个变量
ansible localhost -m debug -a "var=ansible_facts['hostname']"

命令选项 #

连接选项 #

bash
# 指定清单文件
ansible all -m ping -i inventory/hosts

# 指定用户
ansible all -m ping -u admin

# 指定端口
ansible all -m ping -e "ansible_port=2222"

# 指定私钥文件
ansible all -m ping --private-key=~/.ssh/id_rsa

# 指定密码(不推荐)
ansible all -m ping -k

提权选项 #

bash
# 使用 sudo
ansible all -m apt -a "name=nginx state=present" -b

# 指定提权用户
ansible all -m apt -a "name=nginx state=present" -b --become-user=root

# 指定提权方式
ansible all -m apt -a "name=nginx state=present" -b --become-method=sudo

# 交互式输入 sudo 密码
ansible all -m apt -a "name=nginx state=present" -b -K

执行选项 #

bash
# 并发数
ansible all -m ping -f 10

# 详细输出
ansible all -m ping -v
ansible all -m ping -vv
ansible all -m ping -vvv
ansible all -m ping -vvvv

# 检查模式(模拟执行)
ansible all -m copy -a "src=file dest=/tmp/file" --check

# 差异显示
ansible all -m copy -a "src=file dest=/tmp/file" --check --diff

# 超时设置
ansible all -m ping --timeout=30

主机选择 #

bash
# 所有主机
ansible all -m ping

# 特定组
ansible webservers -m ping

# 多个组
ansible webservers:databases -m ping

# 排除组
ansible all:!databases -m ping

# 组交集
ansible 'webservers:&production' -m ping

# 通配符
ansible 'web*' -m ping

# 正则表达式
ansible '~web[0-9]+' -m ping

# 特定主机
ansible web1 -m ping

# 多个主机
ansible web1,web2 -m ping

# 使用序号
ansible webservers[0] -m ping

实用场景 #

快速检查 #

bash
# 检查所有主机连通性
ansible all -m ping

# 检查磁盘空间
ansible all -a "df -h"

# 检查内存使用
ansible all -a "free -m"

# 检查系统负载
ansible all -a "uptime"

# 检查服务状态
ansible all -m shell -a "systemctl status nginx"

# 检查开放端口
ansible all -m shell -a "ss -tlnp"

批量操作 #

bash
# 批量创建目录
ansible all -m file -a "path=/tmp/mydir state=directory"

# 批量复制文件
ansible all -m copy -a "src=config.conf dest=/etc/app/config.conf"

# 批量安装软件
ansible webservers -m apt -a "name=nginx state=present" -b

# 批量重启服务
ansible webservers -m service -a "name=nginx state=restarted" -b

# 批量更新系统
ansible all -m apt -a "update_cache=yes upgrade=dist" -b

信息收集 #

bash
# 收集所有主机信息
ansible all -m setup > facts.json

# 收集特定信息
ansible all -m setup -a "filter=ansible_distribution*" --tree facts/

# 查看主机 IP
ansible all -m setup -a "filter=ansible_default_ipv4"

# 查看主机名
ansible all -m setup -a "filter=ansible_hostname"

# 查看内核版本
ansible all -m setup -a "filter=ansible_kernel"

故障排查 #

bash
# 查看日志
ansible all -m shell -a "tail -100 /var/log/syslog"

# 查看进程
ansible all -m shell -a "ps aux | grep nginx"

# 查看网络连接
ansible all -m shell -a "netstat -tlnp"

# 查看防火墙状态
ansible all -m shell -a "ufw status"

# 测试端口连通性
ansible all -m shell -a "nc -zv 192.168.1.100 80"

输出格式 #

默认输出 #

bash
ansible all -m ping

# 输出
web1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
web2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

JSON 输出 #

bash
ansible all -m ping -o

# 输出
web1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "ping": "pong"}
web2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "ping": "pong"}

常见问题 #

问题一:命令执行失败 #

bash
# 错误信息
web1 | FAILED | rc=1 >>
/bin/sh: 1: command: not found

# 解决方案
# 检查命令是否存在
ansible web1 -a "which command"

问题二:权限不足 #

bash
# 错误信息
web1 | FAILED! => {
    "msg": "Missing sudo password"
}

# 解决方案
# 添加 -b 选项
ansible all -m apt -a "name=nginx state=present" -b -K

问题三:Python 解释器未找到 #

bash
# 错误信息
web1 | FAILED! => {
    "msg": "The module failed to execute correctly, you probably need to set the interpreter."
}

# 解决方案
# 指定 Python 解释器
ansible all -m ping -e "ansible_python_interpreter=/usr/bin/python3"

Ad-hoc vs Playbook 选择 #

text
┌─────────────────────────────────────────────────────────────┐
│                     使用场景对比                             │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  使用 Ad-hoc 命令          使用 Playbook                    │
│  ─────────────────        ─────────────────                 │
│  一次性任务                可重复任务                        │
│  简单操作                  复杂逻辑                          │
│  快速检查                  正式部署                          │
│  临时调试                  生产环境                          │
│  紧急修复                  版本控制                          │
│  信息收集                  团队协作                          │
│                                                              │
└─────────────────────────────────────────────────────────────┘

下一步 #

现在你已经掌握了 Ad-hoc 命令的使用,接下来学习 Playbook 基础 了解如何编写可重复的自动化任务!

最后更新:2026-03-29