【Day 73】Linux-自动化工具-Ansible

一、自动化工具

在自动化运维领域,PuppetAnsibleSaltStack 是主流的三款工具,均能实现 "批量管控、配置管理、任务编排" 核心需求,但在架构设计、使用场景、操作复杂度上差异显著。

维度 Puppet Ansible SaltStack
核心定位 企业级配置管理 轻量级自动化工具 分布式混合工具
开发语言 Ruby Python Python
架构模式 主从架构(C/S) 需 Agent 常驻 无服务架构(无 C/S) 基于 SSH/API 混合架构(支持 C/S Agent 模式、无 Agent 模式)
默认通信协议 HTTPS(443 端口) SSH(22 端口,默认)/Ansible Tower API ZeroMQ(4505/4506 端口)
配置语法 自定义 DSL (Puppet Language) YAML/INI YAML(States/Modules) Python(自定义模块)
并发能力 中等(依赖主节点调度,并发数受限) 低(SSH 串行 / 并行需手动配置,大规模易卡顿) 高(ZeroMQ 异步通信,支持万级节点并发)

二、Ansible

(一)介绍

Ansible 是基于 Python 语言开发的轻量级自动化运维工具,核心作用是通过统一的控制节点,实现对多台被管理节点的 "批量管控",涵盖命令执行、配置管理、软件部署、任务编排等场景,广泛应用于中小型运维团队或无复杂分布式需求的自动化场景。

特性 说明
轻量级架构 对比 SaltStack(重量级分布式工具),Ansible 无需在被管理节点部署 Agent 进程,降低运维复杂度和资源占用
基于 SSH 协议 依赖系统原生 SSH 协议实现通信(默认 22 端口),无需额外配置通信组件,兼容性强
无服务 / 无代理(No Server & No Agent) 控制节点无需启动常驻服务,被管理节点无需安装 Agent,仅需确保 SSH 可连接且 Python 环境正常
丰富的 API 接口 支持通过 API 与其他系统(如 Jenkins、Zabbix)集成,实现自动化流程联动
模块化设计 内置上千个模块,可直接调用完成常见运维操作,也支持自定义模块扩展
支持幂等性 重复执行同一任务不会产生异常结果(如 "安装软件" 任务,已安装则跳过),确保操作安全性

(二)Ansible 安装部署(CentOS 7)

1、安装 Ansible

CentOS 7 默认 yum 源不含 Ansible,需先配置 EPEL 源,再通过 yum 安装。

  • 对于 CentOS 7/RHEL 7 ,EPEL 源默认提供的 Ansible 最高稳定版为 2.9.27(长期维护版,已停止主要功能更新,但仍有安全补丁支持);
  • 对于 Ansible 2.10 和更高版本,可以使用pip安装 Ansible 软件包。有关详细信息,请参见安装 Ansible。可以从https://releases.ansible.com/ansible/下载较旧的 Ansible 版本。
  • Ansible 2.10 版本之前 ,不存在 "ansible-core" 这个概念。之后Ansible 官方做了拆分:
  • 拆分出 ansible-core:作为 Ansible 的 "核心引擎",是 Ansible 运行的 "最小依赖",仅包含最基础的功能(如 Playbook 解析器、任务调度器、核心模块(command/shell/file 等)、通信层(SSH 连接));保留 Ansible 发行版(如 Ansible 10、Ansible 9):作为 "完整套装",基于 ansible-core 构建,额外包含 大量社区维护的模块 / 插件 / 集合(如 ansible.posix(系统模块)、community.general(通用模块)、amazon.aws(AWS 云模块)等)。
  • 可以简单理解为:Ansible 发行版 = ansible-core + 一堆常用模块/集合
  • GitHub - ansible/ansible at stable-2.20
bash 复制代码
[root@zabbix_server ~] wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
[root@zabbix_server ~] yum install -y ansible

[root@zabbix_server ~] rpm -q ansible
# ansible-2.9.27-1.el7.noarch  # 显示版本,说明安装成功

[root@zabbix_server ~] ansible --version
# ansible 2.9.27
# config file = /etc/ansible/ansible.cfg  # 默认配置文件路径

// 这里直接用 2.9.27简单学习。

2、配置主机清单文件

//(/etc/ansible/hosts)

Ansible 的 "主机清单" 是核心配置文件,用于定义 "哪些节点需要被管理",支持 "未分组" 和 "分组" 两种写法,便于按业务场景(如 web 服务器、数据库服务器)批量操作。

(1) 未分组的写法

//(适用于节点数量少、无业务分类的场景)

bash 复制代码
# 直接在 /etc/ansible/hosts 中写入被管理节点的 IP 或主机名:
[root@zabbix_server ~] vim /etc/ansible/hosts
192.168.140.11  
192.168.140.12  

# 通过 ansible all -m ping 命令,测试所有节点的连通性(all 代表 "所有清单中的节点",-m ping 代表调用 ping 模块):
[root@zabbix_server ~] ansible all -m ping
192.168.140.11 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"  # 自动识别被管理节点的Python路径
    }, 
    "changed": false,  # 任务未修改节点状态(幂等性体现)
    "ping": "pong"     # 连通成功的标志
}
192.168.140.12 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
(2)分组的写法

//(适用于节点多、按业务分类的场景)

bash 复制代码
# 通过 [组名] 定义分组,同一节点可属于多个组(如 192.168.140.12 既属于 web 组,也属于 db 组):
[root@zabbix_server ~] vim /etc/ansible/hosts
# 清空或注释之前的未分组内容,添加以下分组配置
[web]  # 定义"web服务器组"
192.168.140.158

[db]   # 定义"数据库服务器组"
192.168.140.20  # 同一节点可加入多个组

# 指定组名(如 web、db)测试连通性,仅对目标组的节点生效: 测试 web 组节点
[root@zabbix_server ~] ansible web -m ping
# 此时没有设置免密、也没有配置密码信息,所以会出错

3、解决Permission denied

(1)配置 SSH 免密登录

Ansible 默认通过 SSH 连接被管理节点,配置免密登录可避免每次执行任务输入密码,提升操作效率(非强制)。

① 在控制节点生成 SSH 密钥对

在 Ansible 控制节点(如 zabbix_server)执行以下命令,生成 RSA 密钥对(一路回车,不设置密码,简化操作):

bash 复制代码
[root@zabbix_server ~] ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):  # 回车默认路径
Enter passphrase (empty for no passphrase):  # 回车不设密码
Enter same passphrase again:  # 再次回车确认
Your identification has been saved in /root/.ssh/id_rsa.  # 私钥(本地保存,不可泄露)
Your public key has been saved in /root/.ssh/id_rsa.pub.   # 公钥(需分发到被管理节点)

② 将公钥分发到被管理节点

通过 ssh-copy-id 命令,将控制节点的公钥复制到被管理节点(如 192.168.140.11192.168.140.12),首次执行需输入被管理节点的 root 密码:

bash 复制代码
# 分发到 192.168.140.11
[root@zabbix_server ~] ssh-copy-id root@192.168.140.11
root@192.168.140.11 password:  # 输入被管理节点root密码

# 分发到 192.168.140.12
[root@zabbix_server ~] ssh-copy-id root@192.168.140.12

③ 验证免密登录

无需输入密码即可登录被管理节点,说明配置成功:

bash 复制代码
[root@zabbix_server ~]# ssh root@192.168.140.11
Last login: Wed Oct 11 10:00:00 2024 from zabbix_server.linux.com
[root@node1 ~]#  # 成功登录,无需密码

(2)添加非免密的主机

若部分被管理节点未配置 SSH 免密(如临时节点),可在主机清单中直接指定 SSH 用户名、密码、端口(需先安装 sshpass 工具,用于处理密码输入)。

① 安装 sshpass 工具

bash 复制代码
[root@host_21 ~] yum install -y sshpass # 可能被当成依赖下过

② 在主机清单中配置非免密节点

bash 复制代码
[root@host_21 ~] vim /etc/ansible/hosts 
# 通过 ansible_ssh_user(SSH 用户名)、ansible_ssh_pass(SSH 密码)、
# ansible_ssh_port(SSH 端口,默认 22 可省略)指定节点信息:
[web]  # 定义"web服务器组"
192.168.140.158 ansible_ssh_user="root" ansible_ssh_pass="548165634" ansible_ssh_port=22
192.168.140.159 ansible_ssh_user="root" ansible_ssh_pass="548165634" ansible_ssh_port=22

[no]
192.168.140.51 ansible_ssh_user="root" ansible_ssh_pass="548165634" ansible_ssh_port=22
[db]   # 定义"数据库服务器组"
192.168.140.20 ansible_ssh_user="root" ansible_ssh_pass="548165634" ansible_ssh_port=55555

验证非免密节点连通性

bash 复制代码
[root@host_21 ~] ansible db -m ping
[root@host_21 ~] ansible no -m ping
[root@host_21 ~] ansible web -m ping

4、解决 "Host Key checking" 错误

Ansible 默认会检查被管理节点的 SSH 指纹(保存在 ~/.ssh/known_hosts),非免密节点首次连接时会因指纹未记录报错,需修改 Ansible 配置关闭该检查:

bash 复制代码
[root@zabbix_server ~] vim /etc/ansible/ansible.cfg
# 找到并修改以下配置项(默认注释,取消注释并设为 False)
host_key_checking = False  # 关闭 SSH 指纹检查

(三)Ansible 命令基本用法

bash 复制代码
# 基本语法格式
ansible 被管理机 -m 模块 -a 模块参数

(1)ansible-doc 是 Ansible 自带的模块文档查询工具,用于查看各模块的详细说明、参数列表和使用示例。

bash 复制代码
# 查看指定模块的文档(以 lineinfile 模块为例)
ansible-doc lineinfile

# 查看模块的简要信息(仅显示参数和示例)
ansible-doc -s lineinfile
  • -s--snippet:显示模块的简洁信息,包括参数说明和示例(最常用)
  • -l--list:列出所有可用模块(此版本有3k多个模块)
  • -F--list_files:列出所有模块的文档文件路径
  • -v--verbose:显示更详细的文档内容

(2)Ansible.Builtin --- Ansible 社区文档

  • 直接搜索模块 :页面顶部有搜索框,输入模块名(如 fetchcron),可快速定位到目标模块的文档。

常用模块及示例:

1. shell 模块

**作用:**在远程主机上执行 shell 命令,并且支持所有 shell 特性,如管道操作(|)、重定向(>、>>)、环境变量引用等

bash 复制代码
# 查看系统负载
ansible db -m shell -a 'uptime'

# 查看内存使用情况
ansible db -m shell -a 'free -m'

# 多命令组合执行
ansible db -m shell -a 'df -h | grep /opt'

// 由于 shell 模块会通过远程主机的 shell(默认是 /bin/sh)执行命令,因此在使用特殊字符(如 $、引号等)时,可能需要进行适当的转义,避免本地解析导致命令执行不符合预期。

虽然 shell 模块非常灵活(能执行任意 shell 命令),但 Ansible 仍然提供了大量专用模块(如 copy、file、yum 等),核心原因是 专用模块更安全、更可靠、更易于维护,且能更好地适配自动化场景。

bash 复制代码
- name: 错误示例:未转义 $HOME,被控制节点解析
  hosts: web
  tasks:
    - name: 打印被管理节点的 $HOME
      shell: echo "被管理节点HOME: $HOME"  # 问题:$HOME 会被控制节点优先解析

- name: 正确示例:转义 $HOME,由被管理节点解析
  hosts: web
  tasks:
    - name: 打印被管理节点的 $HOME
      shell: echo "被管理节点HOME: \$HOME"  # 关键:\$ 转义,控制节点不解析

- name: 错误示例:未转义双引号,被控制节点拆分命令
  hosts: web
  tasks:
    - name: 匹配日志中的 "error" 行
      shell: grep "error" /var/log/messages  # 问题:双引号被控制节点当作字符串边界
 # 最终传递给被管理节点的命令会变成 grep error /var/log/messages(丢失了双引号);

- name: 正确示例:转义双引号,保留命令中的引号
  hosts: web
  tasks:
    - name: 匹配日志中的 "error" 行
      shell: grep \"error\" /var/log/messages  # 关键:\" 转义,双引号被保留

- name: 错误示例:复杂命令未转义,管道和变量被破坏
  hosts: web
  tasks:
    - name: 拼接当前用户信息
      shell: whoami | xargs -I {} echo "当前用户: {}"  # 问题:双引号和 {} 被解析
 # 双引号问题:控制节点会丢失 echo "当前用户: {}" 中的双引号,导致命令变成 echo 当前用户: {};
 # 缺少双引号会导致 xargs 传递的 {} 被 shell 当作普通字符,而非占位符。
- name: 正确示例:转义双引号,保留管道和占位符
  hosts: web
  tasks:
    - name: 拼接当前用户信息
      shell: whoami | xargs -I {} echo \"当前用户: {}\"  # 关键:\" 转义双引号

具体来说,使用专用模块而非直接依赖 shell 有以下关键优势:

(1)避免 "命令注入" 和 "意外操作" 风险

shell 模块执行的是原始 shell 命令,若命令中包含变量(尤其是用户输入或动态生成的内容),可能存在命令注入风险。

bash 复制代码
例如,假设用 shell 模块删除一个动态生成的文件:

# 危险!若 filename 包含特殊字符(如 "; rm -rf /"),会执行恶意命令
ansible db -m shell -a "rm -f /tmp/{{ filename }}"

而专用模块(如 file)会自动处理变量中的特殊字符,避免解析错误或恶意注入:

# 安全!file 模块会将 path 作为字符串处理,不解析特殊字符
ansible db -m file -a "path=/tmp/{{ filename }} state=absent"

(2)幂等性(Idempotency)保障

Ansible 自动化的核心原则是幂等性:即多次执行同一任务,结果应完全一致(不会重复修改或产生副作用)。shell 模块本身不保证幂等性,需要手动编写复杂命令来实现。例如:

bash 复制代码
# 繁琐且易出错:先检查是否存在,不存在才追加
ansible db -m shell -a 'grep -q "192.168.1.1" /etc/hosts || echo "192.168.1.1 test" >> /etc/hosts'

# 简洁且安全:无论执行多少次,最终文件中只会有一行目标内容
ansible db -m lineinfile -a 'path=/etc/hosts line="192.168.1.1 test"'

**(3)**更精细的参数控制和状态管理

专用模块针对特定场景设计了丰富的参数,能实现精确控制,而 shell 模块需要用冗长的命令组合才能实现同等功能。例如管理服务:

bash 复制代码
# 兼容性差:CentOS 7 用 systemctl,CentOS 6 用 chkconfig
ansible db -m shell -a 'systemctl start vsftpd && systemctl enable vsftpd'


# 跨系统兼容:自动识别 systemd、sysvinit 等,确保状态正确
ansible db -m service -a 'name=vsftpd state=started enabled=yes'

(4)清晰的返回结果和错误处理

专用模块执行后会返回结构化的结果(如是否修改、错误原因等),便于在 Playbook 中判断任务状态或调试。例如复制文件:

bash 复制代码
[root@host_21 ~]# ansible db -m shell -a 'cp /root/file /opt'
192.168.140.20 | CHANGED | rc=0 >>
[root@host_21 ~]# ansible db -m shell -a 'cp /root/file1 /opt'
192.168.140.20 | FAILED | rc=1 >>
cp: 无法获取"/root/file1" 的文件状态(stat): 没有那个文件或目录non-zero return code

[root@host_21 ~]# ansible db -m copy -a 'src=/root/file dest=/opt remote_src=yes'
192.168.140.20 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", 
    "dest": "/opt/file", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "d41d8cd98f00b204e9800998ecf8427e", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "src": "/root/file", 
    "state": "file", 
    "uid": 0
}
[root@host_21 ~]# ansible db -m copy -a 'src=/root/file1 dest=/opt remote_src=yes'
192.168.140.20 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "msg": "Source /root/file1 not found"
}

(5)可读性和可维护性

专用模块的意图更明确,无需阅读复杂的命令逻辑就能理解任务目的。例如:

bash 复制代码
看到 ansible db -m yum -a 'name=vsftpd state=present',立刻能知道是 "安装 vsftpd 软件"。
而看到 ansible db -m shell -a 'yum install -y vsftpd',需要确认命令是否有副作用(如是否会升级依赖)。
# 若安装过程中出现依赖冲突等错误,模块会尝试回滚操作,避免系统处于 "半安装" 的不一致状态;
# 而 shell 执行 yum install 失败时,可能残留部分安装文件,需要手动清理。
2. copy 模块

作用:将控制节点的普通文件或目录推送到被管理节点,原样复制文件(不解析变量)

ansible.builtin.copy 模块 -- 将文件复制到远程位置 --- Ansible 社区文档

  • src= 控制节点上的源文件 / 目录路径(必填,除非用 content 直接生成内容)。
  • dest= 被管理节点上的目标路径(必填)
  • mode= 目标文件 / 目录的权限(如 06440755,八进制格式,需带前导 0)。
  • owner= 属主(用户名或 UID)
  • group= 属组(组名或 GID
  • force=yes/no # 是否强制覆盖目标文件(yes/no,默认 yes
  • content=字符串 # 直接将字符串作为文件内容写入目标文件
  • remote_src=yes/no #
  • directory_mode=权限 # 递归复制目录时,设置目录的权限(文件权限仍由 mode 控制)。
  • backup=yes/no # 若为 yes,覆盖目标文件前会备份原文件(后缀 .bak)
  • copy 模块默认不会解析文件中的变量,如果需要推送带有变量的文件并让变量生效(即替换为实际值),应该使用 template 模块而非 copy 模块。
bash 复制代码
# 推送文件
ansible db -m copy -a 'src=/root/file01 dest=/opt'
# 推送目录(会递归推送目录内所有内容)
ansible db -m copy -a 'src=/root/configs/ dest=/etc/app/'


[root@host_21 ~] ansible db -m copy -a 'src=/opt/work dest=/opt'
[root@host-20 ~]# ls /opt/
# work
[root@host_21 ~] ansible db -m copy -a 'src=/opt/work/ dest=/opt'
[root@host-20 ~]# ls /opt/
# file001  file002  file003

# 推送并指定权限和属主
[root@host_21 ~] ansible db -m copy -a 'src=/etc/hosts dest=/opt/hosts mode=0644 owner=root group=root'
[root@host_21 ~] ansible db -m copy -a 'src=/etc/hosts dest=/opt/hosts mode=0755 owner=root group=root'
# 传两次则会覆盖上一次的
[root@host-20 ~]# ls -dl /opt/hosts 
# -rw-r--r-- 1 root root 360 9月  28 20:23 /opt/hosts
[root@host-20 ~]# ls -dl /opt/hosts 
# -rwxr-xr-x 1 root root 360 9月  28 20:23 /opt/hosts

# 仅当源文件比目标文件新时才推送(增量更新)
ansible db -m copy -a 'src=/root/script.sh dest=/usr/local/bin/ mode=0755 force=no'
# force=no:复制策略为 "不强制覆盖"------ 若被管理节点的 /usr/local/bin/script.sh 已存在,则不执行复制(即使源文件与目标文件内容不同);仅当目标文件不存在时,才会复制。

ansible db -m copy -a 'content="export PATH=/usr/local/bin:$PATH" dest=/etc/profile.d/custom.sh mode=0644'
# content直接写入字符串作为文件内容
  • 若 src 是目录且末尾不带 /,会将目录本身及内容推送到 dest;若带 /,则只推送目录内的内容
  • force=yes(默认)表示强制覆盖目标文件,force=no 则仅在源文件更新时才覆盖
  • 推送大文件时,可配合 validate 参数先验证文件完整性(如 validate='/usr/bin/checksum %s')
3.template模块
  • 严格来说,template 模块不能直接在 ad-hoc 命令(ansible 命令行)中使用,因为 ad-hoc 主要用于简单任务,而 template 依赖本地模板文件和 Jinja2 解析,命令行无法便捷地指定模板内容。
  • playbook、角色、独立任务文件等可以使用 template 模块。
4. fetch 模块

作用:从远程主机拉取文件到控制节点的重要工具

ansible.builtin.fetch 模块 -- 从远程节点获取文件 --- Ansible 社区文档

  • src= 被管理节点上的源文件路径(必须是文件,不能是目录)。
  • dest= 控制节点上的保存路径(会自动创建以远程主机 IP 为名的子目录)
  • 默认会在本地的 dest 路径下,自动创建以「远程主机 IP」命名的子目录,然后把拉取的文件存到这个 IP 子目录里。
  • 比如远程主机 IP 是 192.168.140.11,最终本地路径会是:/opt/192.168.140.11/var/log/messages(连远程文件的原始路径结构也会保留)。
  • flat=yes/no # 若为为yes,则不创建 "远程 IP + 原始路径" 的嵌套目录,直接按指定文件名保存(覆盖模式)。
  • validate_checksum=yes/no # yes(默认),则校验文件哈希值,仅当远程文件与本地文件不一致时才拉取;no 则强制拉取。
  • fail_on_missing=yes/no # yes(默认),当远程文件不存在时任务失败;no 则忽略不存在的文件,继续执行。
  • fetch 模块只能拉取单个文件,若需拉取目录,需先在远程节点打包(如 tar),再拉取压缩包,最后在控制节点解压。
bash 复制代码
# 拉取远程日志文件
ansible db -m fetch -a 'src=/var/log/messages dest=/opt'

# 拉取文件并自定义保存路径结构(不自动创建IP目录)
ansible db -m fetch -a 'src=/var/log/messages dest=/opt/logs/ flat=yes'

# 拉取文件时重命名(避免同名文件覆盖)
ansible db -m fetch -a 'src=/var/log/messages dest=/opt/logs/{{inventory_hostname}_messages flat=yes'

# 仅拉取比本地新的文件(增量拉取)
ansible db -m fetch -a 'src=/var/log/messages dest=/opt/logs/ validate_checksum=yes'

# 查看拉取结果
ls /opt/
# 192.168.140.11  192.168.140.12  ...(以远程主机IP命名的目录)
5. file 模块

作用:管理文件 / 目录(创建、删除、权限修改等)

bash 复制代码
# 修改文件权限和属主
ansible db -m file -a 'path=/opt/file01 mode=600 owner=nobody group=nobody'

# 递归修改目录权限(包括子文件和子目录)
ansible db -m file -a 'path=/opt/app state=directory mode=0755 recurse=yes'

# 创建空文件
ansible db -m file -a 'path=/opt/file02 state=touch'

# 创建目录
ansible db -m file -a 'path=/opt/linux state=directory mode=755'

# 删除文件或目录(递归删除)
ansible db -m file -a 'path=/opt/file02 state=absent'

# 创建符号链接
ansible db -m file -a 'src=/opt/linux path=/opt/link state=link'

# 设置文件的访问时间和修改时间(类似touch命令的 -t 参数)
ansible db -m file -a 'path=/opt/file01 state=file access_time=202405010830.00 modification_time=202405010830.00'

# 创建临时文件(设置特殊权限,如粘滞位sticky bit)
ansible db -m file -a 'path=/tmp/shared state=directory mode=1777'

# 强制删除非空目录(即使目录内有文件也会递归删除)
ansible db -m file -a 'path=/opt/old_data state=absent force=yes'

关键参数补充说明:

  • recurse=yes:对目录生效,递归修改其下所有子文件和子目录的属性
  • force=yes:删除目录时若目录非空,会强制递归删除;创建链接时若目标已存在,会强制覆盖
  • 使用 state=absent 删除文件 / 目录时要格外谨慎,建议先通过 stat 模块确认目标存在性
bash 复制代码
# 先检查文件是否存在,再删除(在Playbook中更常用)
ansible db -m stat -a 'path=/opt/file02'
  • 创建符号链接时,src 建议使用绝对路径,避免因工作目录变化导致链接失效。
  • mode 参数支持两种格式:
    • 数字格式:mode=0755(注意前导 0 不能省略)
    • 符号格式:mode='u=rwx,g=rx,o=rx'(不受 umask 影响,权限设置更精确)
6. lineinfile 模块

作用:管理文件内容(添加、修改、删除行)

bash 复制代码
# 向/etc/hosts添加一行记录
ansible db -m lineinfile -a 'path=/etc/hosts line="192.168.140.10   zabbix_server.linux.com"'

# 替换匹配行(使用regexp)
ansible db -m lineinfile -a 'path=/etc/sysctl.conf regexp="^net.ipv4.ip_forward" line="net.ipv4.ip_forward=1"'

# 删除匹配行
ansible db -m lineinfile -a 'path=/etc/hosts regexp="^192.168.140.10" state=absent'

# 确保行存在且唯一(重复行只保留最后一次设置的内容)
ansible db -m lineinfile -a 'path=/etc/sysctl.conf regexp="^net.core.somaxconn" line="net.core.somaxconn=1024" state=present'

# 在匹配行之前插入新行(insertbefore)
ansible db -m lineinfile -a 'path=/etc/nginx/nginx.conf regexp="^http {" insertbefore=yes line="worker_rlimit_nofile 65535;"'

# 在匹配行之后插入新行(insertafter)
ansible db -m lineinfile -a 'path=/etc/ssh/sshd_config regexp="^Port 22" insertafter=yes line="Port 2222"'

# 仅当文件存在时才操作(避免对不存在的文件报错)
ansible db -m lineinfile -a 'path=/etc/optional.conf line="log_level=info" state=present creates=/etc/optional.conf'

# 备份原文件(修改前自动创建.bak备份)
ansible db -m lineinfile -a 'path=/etc/sudoers regexp="^%wheel" line="%wheel ALL=(ALL) NOPASSWD: ALL" backup=yes'
7. cron 模块

作用:管理计划任务

bash 复制代码
# 添加定时任务(每30分钟同步时间)
ansible db -m cron -a 'name=TimeSync minute=*/30 job="/usr/sbin/ntpdate ntp.aliyun.com &> /dev/null" state=present'

# 禁用定时任务
ansible db -m cron -a 'name=TimeSync state=disabled'

# 删除定时任务
ansible db -m cron -a 'name=TimeSync state=absent'

# 设置每日凌晨 2 点执行备份脚本(指定小时和分钟)
ansible db -m cron -a 'name=BackupScript hour=2 minute=0 job="/root/backup.sh &> /var/log/backup.log" state=present'

# 设置每周日凌晨 3 点清理日志(指定星期)
ansible db -m cron -a 'name=CleanLogs weekday=0 hour=3 minute=0 job="find /var/log -name *.log -mtime +7 -delete" state=present'

# 设置每月 1 号执行系统更新(指定日期)
ansible db -m cron -a 'name=SystemUpdate day=1 hour=4 minute=0 job="yum update -y &> /dev/null" state=present'

# 添加带环境变量的定时任务(如指定 PATH)
ansible db -m cron -a 'name=CustomJob env=yes job="PATH=/usr/local/bin:$PATH; script.sh" state=present'

# 为特定用户添加定时任务(默认是执行 ansible 的用户,通常是 root)
ansible db -m cron -a 'name=UserJob user=test minute=*/10 job="echo hello > /home/test/hello.txt" state=present'
  • name:任务名称,用于唯一标识任务(修改或删除时必须一致)
  • env=yes:将任务标记为环境变量定义(而非执行命令),适合设置 PATHMAILTO
  • user:指定任务所属用户(默认是当前执行 ansible 的用户)
  • comment:为任务添加注释(会显示在 crontab 中)
8. yum 模块

作用:管理 RPM 包(适用于 CentOS/RHEL 系统)参数:

  • state: present(安装)、absent(卸载)、latest(更新到最新版)
bash 复制代码
# 安装vsftpd
ansible db -m yum -a 'name=vsftpd state=present'

# 卸载vsftpd
ansible db -m yum -a 'name=vsftpd state=absent'

# 更新到最新版
ansible db -m yum -a 'name=vsftpd state=latest'

# 批量安装多个包
ansible db -m yum -a 'name=httpd,mysql-server state=present'

# 从指定 yum 仓库安装包(需提前配置好仓库)
ansible db -m yum -a 'name=nginx enablerepo=epel state=present'

# 安装特定版本的包
ansible db -m yum -a 'name=httpd-2.4.6-97.el7.centos state=present'

# 安装本地 RPM 包(需先通过 copy 模块推送至远程)
ansible db -m yum -a 'name=/tmp/nginx-1.20.1.rpm state=present'

# 卸载包并清除依赖(仅删除无其他依赖的包)
ansible db -m yum -a 'name=vsftpd state=absent autoremove=yes'

# 更新所有已安装的包(慎用,可能导致兼容性问题)
ansible db -m yum -a 'name=* state=latest'

# 清理 yum 缓存
ansible db -m yum -a 'name=* state=clean'
  • enablerepo/disablerepo:临时启用 / 禁用指定仓库(逗号分隔多个仓库名)

  • autoremove=yes:卸载包时自动删除无用依赖(类似 yum autoremove

  • disable_gpg_check=yes:跳过 GPG 签名验证(不推荐,仅临时用于无签名包)

  • installroot:指定安装根目录(适用于容器或 chroot 环境)

  • 使用 state=latest 时需谨慎,尤其是生产环境:

    • 可能将包升级到不兼容的新版本(如从 PHP 7.4 升级到 8.0)
    • 建议针对特定包使用,而非 name=*(更新所有包)
9. service 模块

作用:管理系统服务

bash 复制代码
# 启动vsftpd并设置开机自启
ansible db -m service -a 'name=vsftpd state=started enabled=yes'

# 停止服务
ansible db -m service -a 'name=vsftpd state=stopped'

# 重启服务
ansible db -m service -a 'name=vsftpd state=restarted'

# 重新加载配置
ansible db -m service -a 'name=vsftpd state=reloaded'

# 检查服务状态(不改变状态,仅返回当前运行情况)
ansible db -m service -a 'name=vsftpd state=started'

# 禁用服务开机自启(但保持当前运行状态)
ansible db -m service -a 'name=vsftpd enabled=no'

# 强制重启服务(即使服务未运行也尝试启动)
ansible db -m service -a 'name=nginx state=restarted force=yes'

# 为服务指定运行用户(部分服务支持,如 nginx、apache)
ansible db -m service -a 'name=nginx state=started user=nginx'

# 启动服务并设置超时时间(默认30秒,适用于启动较慢的服务)
ansible db -m service -a 'name=mysql state=started timeout=60'
  • 对于 reloaded 状态,并非所有服务都支持(如 vsftpd 通常不支持 reload,需用 restarted
10. user/group 模块

作用:管理用户和用户组

bash 复制代码
# 创建用户并加入组
ansible db -m user -a 'name=test groups=it uid=2000 shell=/sbin/nologin home=/home/test state=present'

# 删除用户(保留家目录)
ansible db -m user -a 'name=test state=absent remove=no'
# 创建系统用户(无家目录,UID 通常小于 1000)
ansible db -m user -a 'name=nginx system=yes shell=/sbin/nologin state=present'

# 设置用户密码(需提供加密后的密码,可通过 python 生成)
# 生成加密密码:python -c 'import crypt; print(crypt.crypt("明文密码", crypt.mksalt(crypt.METHOD_SHA512)))'
ansible db -m user -a 'name=test password="$6$rounds=656000$abc123$xyz..." state=present'

# 锁定/解锁用户
ansible db -m user -a 'name=test lock=yes'  # 锁定
ansible db -m user -a 'name=test lock=no'   # 解锁

# 指定用户的附加组(groups 为主要组,append=yes 表示不覆盖原有附加组)
ansible db -m user -a 'name=test groups=it append=yes groups=wheel,admin'

# 创建用户时指定过期时间(YYYY-MM-DD)
ansible db -m user -a 'name=tempuser expires=2024-12-31 state=present'

# 创建用户组
ansible db -m group -a 'name=it state=present gid=1000'

# 删除用户组
ansible db -m group -a 'name=it state=absent'
# 创建附加组(系统组)
ansible db -m group -a 'name=devops system=yes gid=3000 state=present'

# 修改用户组 GID
ansible db -m group -a 'name=it gid=1001 state=present'

# 创建嵌套组(将组作为另一个组的成员)
ansible db -m group -a 'name=admin state=present'
ansible db -m group -a 'name=dev members=admin state=present'  # dev 组包含 admin 组

设置密码时,必须使用加密后的字符串(Ansible 不支持直接传入明文密码)。生成方法:

复制代码
# 在控制节点执行 python 命令生成 SHA512 加密密码
python3 -c 'import crypt; print(crypt.crypt("你的明文密码", crypt.mksalt(crypt.METHOD_SHA512)))'

删除用户时:

  • remove=yes 会同时删除用户的家目录和邮件目录(谨慎使用)
  • remove=no(默认)仅删除用户账号,保留家目录
11. script 模块

作用:在远程主机执行本地脚本

bash 复制代码
# 执行本地脚本(脚本权限需可执行)
ansible db -m script -a '/root/test.sh'

# 带参数执行脚本
ansible db -m script -a '/root/backup.sh /data 7'

# 执行脚本时指定远程执行用户(默认使用ansible连接用户,通常是root)
ansible db -m script -a 'sudo_user=test /root/script.sh'

# 执行脚本时传递环境变量
ansible db -m script -a 'environment="PATH=/usr/local/bin:$PATH" /root/script.sh'

# 为脚本设置执行超时时间(单位秒,默认30秒)
ansible db -m script -a 'timeout=60 /root/long_running_script.sh'

# 执行脚本时忽略错误(即使脚本返回非0状态码也视为成功)
ansible db -m script -a 'args="--ignore-errors" /root/script.sh'
  • sudo_user:指定在远程主机上执行脚本的用户(需要该用户有执行权限)
  • environment:设置执行脚本时的环境变量(如 PATH、LD_LIBRARY_PATH 等)
  • timeout:脚本执行的超时时间,超过此时间会被终止
  • args:传递给脚本的额外参数(也可以直接跟在脚本路径后,如示例中的 /root/backup.sh /data 7

12、unarchive 模块作用:解压压缩包(支持本地解压和从远程拉取后解压)

bash 复制代码
# 解压本地压缩包到远程主机
ansible db -m unarchive -a 'src=/root/files.tar.gz dest=/opt/ mode=0755'

# 从远程URL下载并解压
ansible db -m unarchive -a 'src=https://example.com/files.tar.gz dest=/opt/ remote_src=yes'
相关推荐
黄沐阳3 小时前
网络产品报价指南--S5735系列交换机
运维·服务器·网络·智能路由器
陌路203 小时前
Linux 12mybash的实现
linux
WnHj3 小时前
带密码加密机制的自动 FTP 拉取脚本
linux·运维·服务器·网络
脑子缺根弦3 小时前
辉视融合服务器:强劲驱动电视信息发布,直播点播流畅运行,赋能高效传播
linux·运维·服务器
。TAT。3 小时前
Linux - 命令行参数与环境变量
linux·学习
qq_339191143 小时前
aws ec服务器设置密码登录,ec服务器root登录 aws服务器初始化配置
服务器·github·aws
zl_dfq3 小时前
Linux 之 【基本指令 与 shell命令以及运行原理】
linux
野犬寒鸦3 小时前
从零起步学习MySQL || 第一章:初识MySQL及深入理解内部数据类型
java·服务器·数据库·后端·mysql
海域云SeaArea_3 小时前
边缘服务器 FTP/TFTP 服务搭建与使用(Docker 方式)
运维·服务器