ansible配置与模块介绍

ansible

文章目录

Ansible 是一款开源的自动化工具,主要用于 配置管理、应用部署、任务自动化IT 流程编排 。它基于 Python 开发,采用 "无代理" 架构(通过 SSH 协议与目标主机通信,无需在目标主机安装客户端),操作简单且功能强大,广泛应用于云环境、服务器集群等场景。

核心特点

  1. 无代理架构:仅需控制节点安装 Ansible,目标主机通过 SSH 即可被管理(支持密码或密钥认证)。
  2. 简单易用:使用 YAML 格式编写自动化脚本(Playbook),语法直观,易于阅读和维护。
  3. 模块化设计:内置数千个模块(Module),覆盖用户管理、文件操作、服务控制、包管理等场景,也支持自定义模块。
  4. 并行执行:可同时对多台主机执行任务,提高自动化效率。
  5. 幂等性:重复执行相同任务不会产生意外结果(如 "确保服务启动",多次执行仍为启动状态)。

批量管理工具选型

工具 说明 缺点 核心定位与适用场景
xshell 不适应机器过多场景,需要连接后才能用。 - 交互式 SSH 工具,适合单台 / 少量机器的手动远程操作(如临时命令执行、日志查看),但无法批量自动化。
for+ssh/scp + 秘钥认证 秘钥认证,免密码登录;scp 传输文件 / 脚本;ssh 远程执行命令或脚本。 串行(逐台执行,效率低) 脚本化 SSH 方案,通过 Shell 脚本结合 SSH/SCP 实现简单自动化(如批量传文件、执行命令),但缺乏并行能力,机器多时光伏化严重。
saltstack 需要安装客户端。 - 客户端 - 服务端架构的配置管理工具,需在被管理节点安装 Salt 客户端,优势是执行速度快、适合超大规模集群,但部署门槛高于无客户端工具。
ansible 无客户端(秘钥认证);批量部署环境。 python 版本不要太旧;红帽的(依赖 Python 环境,旧版本可能兼容问题) 无代理配置管理工具,仅控制节点需装 Ansible,目标节点通过 SSH 通信,适合中小规模批量配置、应用部署、任务自动化,学习成本低且易用性强。
Terraform 关注基础设施(云环境),一键创建 100 台云服务器,1 键创建负载均衡、数据库产品。 - 基础设施即代码(IaC)工具,专注于云资源(如服务器、负载均衡、数据库)的批量创建与编排,而非已有服务器的配置管理,适合云环境的资源自动化交付。

ansible管理架构

  • 先配置好密钥认证
  • 主机清单,通过主机清单(inventory)连接管理被控端
  • ad-hoc:命令执行模块
  • playbook:使用playbook剧本(核心)

环境准备

作用 主机 ip
ansible管理端 m01(增加核心输,4c或8c) 10.0.0.61/172.16.1.61
被管理端:其他所有机器 web01,web02,db01,nfs01,backup

部署ansible

bash 复制代码
如何部署ansible,使用pip工具安装.
pip 安装python软件包.
#0.安装pip工具
yum install -y python3-pip

#1.升级pip
python3 -m pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple --upgrade pip

#2.pip源(加速pip下载软件)
pip3 config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

#3.安装ans
pip3 install  ansible

#4.配置ans
mkdir -p /etc/ansible/ 
cat >/etc/ansible/ansible.cfg<<'EOF'
[defaults]
host_key_checking = False
deprecation_warnings = False
interpreter_python=/usr/bin/python3
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
EOF
bash 复制代码
可以尝试升级python(所有节点)
#升级python到python3.11
下载,解压,进入目录

配置
#./configure --enable-optimizations --with-ssl
#make -j `nproc`
#make install

配置主机清单

bash 复制代码
[root@m01 ~]# cat /etc/ansible/hosts 
#主机清单文件 inventory
[lb]
#指定用户,端口,密码
172.16.1.5 ansible_user=root ansible_port=22 ansible_password=Lidao66
172.16.1.6

[web]
172.16.1.7
172.16.1.8

[db]
172.16.1.51
172.16.1.52

[backup]
172.16.1.41

[nfs]
172.16.1.31

#创建data分组,子组有db,nfs,backup
[data:children]
db
backup
nfs

ansible -i hosts data -m ping
  • windows服务器的ansible lnventory(主机清单)
bash 复制代码
[win_servers]
10.0.0.10   ansible_user=administrator     ansible_password=xxxx
10.0.0.10   ansible_user=administrator     ansible_password=xxxx
10.0.0.10   ansible_user=administrator     ansible_password=xxxx
10.0.0.10   ansible_user=administrator     ansible_password=xxxx
10.0.0.10   ansible_user=administrator     ansible_password=xxxx
10.0.0.10   ansible_user=administrator     ansible_password=xxxx

ansible_connection="winrm"  # 连接方式:使用WinRM(Windows远程管理协议,替代SSH)
ansible_port=5985          # WinRM端口:5985为HTTP端口(非加密),5986为HTTPS端口(加密,生产环境推荐)
ansible_winrm_transport="ntlm"  # WinRM认证方式:NTLM(适用于非域环境,域环境可改用kerberos)
ansible_winrm_server_cert_validation=ignore  # 忽略服务器证书验证(测试环境常用,生产环境建议启用验证)

使用脚本分发密钥

bash 复制代码
#!/bin/bash
##############################################################
# File Name: change.sh
# Version: V1.0
# Author: song
# Organization: 
# Description:
##############################################################
# 颜色输出函数
redecho(){
  str=$*
  echo -e "\E[1;31m${str}\E[0m"
}
greenecho(){
  str=$*
  echo -e "\E[1;32m${str}\E[0m"
}
yellowecho(){
  str=$*
  echo -e "\E[1;33m${str}\E[0m"
}
blueecho(){
  str=$*
  echo -e "\E[1;34m${str}\E[0m"
}

ips=/shf/ip.txt
key_dir="$HOME/.ssh/"


error_exit(){
  redecho "Error: $1"
  exit 1
}

#检查系统
dir_OS=/etc/os-release
if [ -f $dir_OS ];then
    source $dir_OS
else
  echo "没有此版本"
  exit 1
fi


check_cmd(){
  case $ID in
   kylin)
   if ! which sshpass ;then
    yum install -y sshpass >/dev/null || error_exit "安装失败,请检查网络"
    greenecho "安装成功"
  fi
   if ! which nc >/dev/null 2>&1;then
    yum install -y nc >/dev/null 2>&1 || error_exit "安装失败,请检查网络"
    greenecho "安装成功"
  fi
   ;;
   ubuntu)
    if ! which sshpass ;then
    apt install -y sshpass >/dev/null || error_exit "安装失败,请检查网络"
    greenecho "安装成功"
  fi
   if ! which nc ;then
    apt install -y netcat >/dev/null || error_exit "安装失败,请检查网络"
    greenecho "安装成功"
  fi
  ;;
  *)
   yellowecho "没有这个版本"
   exit 1
   ;;
esac
}
#创建密钥
create_key(){
  local key_file="$HOME/.ssh/id_rsa"
 [ ! -f ${key_file}  ] && {
     ssh-keygen -t rsa -f ${key_file}   -P '' >/dev/null 2>&1 || error_exit "创建密钥失败"
     greenecho "密钥创建成功,在${key_dir}目录下"
  }
}

fenfa_check(){
  local user_ip
  if [ -f  "${HOME}/.ssh/known_hosts" ];then
      user_ip=`cat ~/.ssh/known_hosts |awk '{print $1}'`
  fi
  
  if [ ! -f ${ips}  ];then
cat >/shf/ip.txt<<EOF 
10.0.0.5,root,Lidao666,22
10.0.0.6,root,Lidao666,22
10.0.0.7,root,Lidao666,22
10.0.0.8,root,Lidao666,22
10.0.0.9,root,Lidao666,22
10.0.0.10,root,Lidao666,22
10.0.0.31,root,Lidao666,22
10.0.0.41,root,Lidao666,22
10.0.0.51,root,Lidao666,22
10.0.0.52,root,Lidao666,22
10.0.0.211,root,Lidao666,22
10.0.0.141,root,1,22
EOF
fi

  while IFS= read -r line;do
  [ -z "$line" ] || [[ "$line" =~ ^# ]] && continue

  IFS=',' read -r ip user passwd port <<< "$line"

  if [ -z "$ip" ] || [ -z "$user" ] || [ -z "$passwd" ]; then
      yellowecho "配置行格式错误:'$line',跳过"
      continue
    fi



  local is_known=0
   while  read -r know_ip;do
   if [[ "${know_ip}" == "$ip"  ]];then
     is_known=1
     break
   fi
  done <<< "$user_ip"

   if [ $is_known  -eq 1 ];then
     greenecho "IP $ip:$port(用户${user}) 已配置秘钥"
     continue
   fi

   if ! nc -z -w 1 "${ip}" "${port}" >/dev/null 2>&1;then
       yellowecho "IP $ip 不可达(或不在线),跳过"
      continue
    fi

    sshpass -p "$passwd" ssh-copy-id -o StrictHostKeyChecking=no -o Port="${port}"  ${user}@${ip} >/dev/null 2>&1 || error_exit "$IP $line 密钥分发失败"
    greenecho "IP ${ip}:${port}(用户${user}) 密钥分发成功"
  done<${ips}
}

main(){
check_cmd 
create_key
fenfa_check
}
main

检查秘钥认证

  • ping模块,检查秘钥认证是否ok
bash 复制代码
#全部检查
ansible all -m ping

#指定组检查
ansible web,db -m ping

#指定hosts文件
ansible -i /server/ansible/hosts web,db -m ping

模块

Ansible 文档

  • 应用:
    • 命令行使用,一般是临时
    • 写在剧本中(playbook)
模块分类 模块 说明 / 选项
执行命令 / 脚本 command 一般用于执行简单命令;不支持特殊符号!() ...`` $;默认的模块。
执行命令 / 脚本 shell command类似,支持特殊符号。
执行命令 / 脚本 script 1. 分发 - 脚本 (管理端指定的文件);2. 执行脚本 (运行);3. 删除脚本
文件,目录 file 支持touchmkdirrmchownchmodln -s操作;用于文件、目录、软连接管理;path= 路径 (目录或目录下文件);src= 源文件 (创建链接);mode=0644、0755、usergroupstate=touch (文件)/directory (目录)/link (软连接)/absent (删除)
用户模块 user 支持useradduserdelpasswd批量添加 / 删除用户、修改密码;参数包括nameuidshellcreate_homestate: present (添加)、absent (删除)
用户组模块 group 参数包括namegidstate
安装软件包 yum/apt name: 软件包名字;state: present (安装)、absent (删除)
分发配置文件 copy 类似scp,用于分发配置文件、压缩包(不要分发目录 );src= 管理机文件路径;dest= 被管理机路径;可设置mode=0644、0755、usergroup
服务管理 systemd 用于服务的启动、停止、重启及开机自启管理;name= 服务名字;enabled= 是否开机自启动 (yes/no);state=started、stopped、restarted、reloaded

模块文档查询

bash 复制代码
#列出所有模块
ansible-doc -l

#查看模块简要参数
ansible-doc -s copy

#查看模块完整文档
ansible-doc file

执行命令(shell/command)

bash 复制代码
#默认就是command
ansible -i hosts data -m command -a 'hostname'



#包含特殊符号
ansible -i hosts data -m shell -a 'touch /tmp/shf{1..10}.txt'
参数名 作用 示例
free_form (核心,无显式参数名)要执行的命令内容 command: docker pull xxx
chdir 执行命令前,先切换到指定目录 chdir: /server/ansible
creates 若指定文件存在,则跳过执行该命令(幂等性) creates: /usr/bin/docker(docker 存在则跳过安装)
removes 若指定文件不存在,则跳过执行该命令(幂等性) removes: /var/run/docker.sock(docker 未启动则跳过)
register 将命令执行结果(输出、返回码等)保存到变量,供后续使用 register: pull_result
changed_when 自定义 "任务是否标记为 changed"(默认命令执行成功就标 changed) changed_when: "'Downloaded' in pull_result.stdout"
failed_when 自定义 "任务失败的条件"(默认非 0 返回码则失败) failed_when: pull_result.rc != 0 and 'exists' not in pull_result.stderr
warn 是否开启命令告警(比如使用不安全的 shell 语法),默认 yes warn: no(关闭告警)
timeout 命令超时时间(秒),默认无超时 timeout: 60(docker pull 超时 1 分钟)

执行脚本(script)

  • 分发脚本,执行脚本,删除脚本
bash 复制代码
#执行脚本
ansible -i hosts data -m script -a '/server/scripts/check_cfg.sh'

#被管理端的脚本位置
root@web01 ~]# tree .ansible/
.ansible/
└── tmp
    ├── ansible-tmp-1762749237.7139132-7195-73449827837603
    │   └── AnsiballZ_command.py
    └── ansible-tmp-1762765984.5945835-3536-158988386023671
        └── check_cfg.sh

输出调试信息(debug)

Ansible 的 debug 模块是用于在 Playbook 执行过程中输出调试信息的核心工具,主要用于验证变量值、任务执行结果、条件判断逻辑等,帮助排查 Playbook 中的问题。它是 Ansible 调试中最常用的模块之一

参数 作用
msg 自定义输出消息(支持 Jinja2 变量引用,如 msg: "当前主机: {``{ inventory_hostname }}")。
var 直接指定要打印的变量名(无需 {``{ }} 包裹,如 var: ansible_facts['os_family'])。
verbosity 控制输出级别(默认 0,即总是显示;设为 1 则需 ansible-playbook -v 才显示,以此类推)。

示例

yaml 复制代码
- name: 示例:输出自定义消息
  hosts: all
  vars:
    app_name: "myapp"
    version: "1.0.0"
  tasks:
    - name: 打印应用信息
      ansible.builtin.debug:
        msg: "正在部署 {{ app_name }},版本:{{ version }},目标主机:{{ inventory_hostname }}"

文件/目录(file)

参数 说明 示例
path/dest/name 目标文件 / 目录 / 软链接的路径(必选参数) path: /tmp/test.txt``dest: /data/app
state 控制资源的状态 :- file:确保是文件(默认,若路径不存在则创建空文件)- directory:确保是目录(不存在则创建)- link:创建软链接(需配合src使用)- absent:删除文件 / 目录(递归删除目录需显式指定) state: directory(确保是目录)state: link(创建软链接)
owner 设置文件 / 目录的所有者(用户名或 UID) owner: www``owner: 1000
group 设置文件 / 目录的所属组(组名或 GID) group: nginx``group: 1001
mode 设置文件 / 目录的权限 (八进制格式,如06440755 mode: 0600(仅所有者可读写)mode: 0775(所有者 / 组可读写执行,其他只读执行)
src 创建软链接时,指定源文件 / 目录的路径 (仅state: link时生效) src: /usr/bin/python3``dest: /usr/bin/python``state: link
recurse 对目录递归设置权限 / 所有者 / 组 (仅state: directory时生效) recurse: yes``mode: 0755``owner: appuser
access_time 修改文件的访问时间 (格式:YYYYMMDDhhmm.sspreserve 保持原时间) access_time: 202511101030.00``access_time: preserve
modification_time 修改文件的修改时间 (格式同access_time modification_time: 202511101030.00
attributes 设置文件系统属性 (如immutable(不可变)、hidden(隐藏),不同系统支持不同) attributes: +i(设置文件为不可变,Linux 适用)attributes: -i(取消不可变)
force 强制创建软链接(若dest已存在文件,会被软链接覆盖) force: yes``src: /new/path``dest: /old/path``state: link

创建目录并设置权限

yaml 复制代码
- name: 确保/data/logs目录存在且权限为755
  ansible.builtin.file:
    path: /data/logs
    state: directory
    mode: 0755

创建软连接

yaml 复制代码
- name: 把python3链接为python
  ansible.builtin.file:
    src: /usr/bin/python3
    dest: /usr/bin/python
    state: link
    force: yes  # 若已存在python文件,强制替换为软链接

递归设置目录权限和所有者

yaml 复制代码
- name: 递归设置/webroot目录的权限和所有者
  ansible.builtin.file:
    path: /webroot
    state: directory
    owner: webuser
    group: webgroup
    mode: 0750
    recurse: yes
  • 创建目录
bash 复制代码
ansible -i hosts  data -m file -a 'path=/app/ans state=directory'
  • 创建文件
bash 复制代码
ansible -i hosts  data -m file -a 'path=/app/ans/shf.txt state=touch'
  • 删除文件/目录
bash 复制代码
#path=指定文件/目录路径,absent是删除
ansible -i hosts  data -m file -a 'path=/app/ans/shf.txt state=absent'
  • 创建软连接
bash 复制代码
#src=源文件,path=目标文件,link创建软连接
ansible -i hosts data -m file -a 'src=/etc/hosts path=/app/ans/hosts.pcom state=link'
  • 创建文件/目录的同时,修改所有者,用户组
bash 复制代码
chown nginx:nginx /app/ans/

#mode 权限  owner 文件所有者 group 文件所属组
ansible -i hosts data  -m file -a 'path=/app/ans/ mode=0700 owner=nginx group=nginx state=directory'
  • 递归修改所有者,用户组,权限
bash 复制代码
chown -R nobody:nobody /app/ans


#recurse=true  递归修改
ansible -i hosts data  -m file -a 'path=/app/ans/ owner=nobody group=nobody recurse=true   state=directory'

用户模块(user)

参数 作用
name 必选,用户名(唯一标识)。
state 用户状态:present(创建 / 确保存在,默认)、absent(删除)。
password 用户密码(必须是加密后的字符串 ,不能用明文,需用 openssl passwd 生成)。
shell 用户默认登录 shell(如 /bin/bash/sbin/nologin,默认 /bin/bash)。
create_home 是否创建家目录:yes(默认)、no(不创建,适合系统用户)。
home 指定家目录路径(默认 /home/用户名)。
groups 用户所属的附加组(多个组用逗号分隔,默认仅属于同名主组)。
append 配合 groups 使用:yes 表示追加附加组(不覆盖原有),no 表示覆盖(默认)。
uid 指定用户的 UID(用户 ID),需唯一。
group 指定用户的主组(默认创建同名主组)。
system 若为 yes,创建系统用户(UID 通常小于 1000,用于服务账号)。
remove 配合 state: absent 使用:yes 表示删除用户时同时删除家目录和邮件目录。
  • 创建用户并配置基本属性
yaml 复制代码
- name: 创建testuser用户
  ansible.builtin.user:
    name: testuser          # 用户名
    uid: 1002               # UID
    group: testgroup        # 主组(名称)
    groups: sudo,dev        # 附加组
    append: yes             # 不覆盖现有附加组
    home: /data/testuser    # 家目录
    shell: /bin/bash        # 登录shell
    comment: "Dev Test User" # 注释
    password: "$6$randon_salt$abcdef..."  # 加密密码
    create_home: yes        # 创建家目录
  • 删除用户并清理家目录
yaml 复制代码
- name: 删除testuser用户
  ansible.builtin.user:
    name: testuser
    state: absent           # 删除用户
    remove: yes             # 同时删除家目录和邮件
  • 创建用户
bash 复制代码
useradd www-data
#添加用户
ansible -i hosts data -m user -a 'name=oldboy state=present'

#添加虚拟用户
useradd -s /sbin/nologin -M www-data

ansible -i hosts data -m user -a 'name=www-data shell=/sbinshell=/sbin/nologin create_home=false state=present'

#添加虚拟用户,指定uid,gid
groupadd -g 2999 www-data
useradd -s /sbin/nologin -M -u 2999 -g www-data www-data

#创建用户组www-data,gid=2999
ansible -i hosts data -m group -a 'name=www-data gid=2999 state=present'
#创建虚拟用户www-data,并指定uid,gid为2999
ansible -i hosts data -m user -a 'name=www-data uid=2999 group=www-data shell=/sbin/nologin create_home=no state=present'
  • 删除用户
bash 复制代码
#删除用户并删除家目录
userdel -r www-data


ansible -i hosts data -m user -a 'name=www-data remove=yes  state=absent'
用户组(group)
参数 作用
name 必选,组名称(唯一标识)。
state 组的状态:present(创建 / 确保存在,默认)、absent(删除)。
gid 指定组的 GID(组 ID),需唯一(避免与现有组冲突)。
system 若为 yes,创建系统组(GID 通常小于 1000,用于服务账号)。
  • 创建用户组
bash 复制代码
#创建用户组,指定gid
ansible -i hosts data -m group -a 'name=www-nfs gid=2999 state=present'
  • 批量修改密码
bash 复制代码
ansible -i hosts  data  -m user   -a 'name=lidao password={{ "oldboy"|password_hash("sha512", "fdsaklfdsajlk234") }}     state=present '

安装软件(yum/apt)

参数 说明 示例
name 必选,指定软件包名称(支持通配符、版本号,或从文件安装)。 name: nginx(安装最新版)name: nginx-1.20.1(指定版本)name: /tmp/nginx.rpm(从本地 RPM 安装)
state 控制软件包状态:- present:确保安装(默认,不升级)- absent:卸载软件包- latest:安装并升级到最新版- installed:同 present- removed:同 absent state: latest(安装并升级到最新)state: absent(卸载)
update_cache 是否更新 yum 缓存(类似 yum makecache):- yes:更新- no:不更新(默认) update_cache: yes(先更新缓存再安装)
enablerepo 临时启用指定 yum 仓库(多个仓库用逗号分隔)。 enablerepo: epel,nginx-stable(启用 EPEL 和 Nginx 稳定版仓库)
disablerepo 临时禁用指定 yum 仓库(多个仓库用逗号分隔)。 disablerepo: base(禁用 base 仓库)
disable_gpg_check 是否跳过 GPG 签名验证(不推荐,仅临时用于无签名包)。 disable_gpg_check: yes
autoremove 卸载软件包时,是否自动删除其依赖的无用包(类似 yum autoremove)。 state: absent``autoremove: yes

安装软件包

yaml 复制代码
- name: 安装并升级 Nginx(CentOS)
  ansible.builtin.yum:
    name: nginx
    state: present
    update_cache: yes  # 先更新缓存

卸载软件包

yaml 复制代码
- name: 卸载 Nginx 并清理依赖(CentOS)
  ansible.builtin.yum:
    name: nginx
    state: absent
    autoremove: yes  # 自动删除无用依赖
  • 安装软件包
bash 复制代码
yum install -y tree

ansible -i hosts data -m yum -a 'name=tree state=present'

#安装多个
ansible -i hosts data -m yum -a 'name=tree,lrzsz,make state=present'
  • 卸载软件包
bash 复制代码
yum remove -y tree

ansible -i hosts data -m yum -a 'name=tree state=absent'

分发配置文件(copy)

参数 说明 示例
src 源路径 (控制节点上的文件 / 目录路径):- 若为文件:直接复制该文件。- 若为目录:默认递归复制目录内所有内容(不包含目录本身,需注意路径末尾是否带/)。- 支持相对路径(相对于 Playbook 所在目录)或绝对路径。 src: ./files/nginx.conf(相对路径,Playbook 同级的 files 目录下)src: /tmp/app.tar.gz(绝对路径)
dest 目标路径 (被控节点上的路径,必选):- 若 src 是文件:dest 可以是文件路径(直接复制为该文件)或目录路径(复制到该目录下,文件名不变)。- 若 src 是目录:dest 必须是目录路径(复制内容到该目录下)。 dest: /etc/nginx/nginx.conf(复制为目标文件)dest: /etc/nginx/(复制到目标目录,文件名不变)
backup 复制前,是否备份目标文件 (若目标存在,备份为 dest.~n~ 格式,如 nginx.conf.~1~)。 backup: yes(备份原有文件)
force 当目标文件已存在时,是否强制覆盖 (对比源文件和目标文件的内容哈希):- yes:内容不同则覆盖(默认)。- no:若目标存在则不复制(即使内容不同)。 force: no(不覆盖已存在的文件)
validate 复制文件后,执行验证命令 (如检查配置文件语法),验证失败则不保留文件。命令中用 %s 指代目标文件路径。 validate: /usr/sbin/nginx -t -c %s(复制 Nginx 配置后,用 nginx -t 验证语法)

基础复制

yaml 复制代码
- name: 复制Nginx配置文件到被控节点
  ansible.builtin.copy:
    src: ./files/nginx.conf  # 控制节点的源文件
    dest: /etc/nginx/nginx.conf  # 被控节点的目标路径
    mode: 0644  # 权限:所有者读写,组和其他只读
    owner: root  # 所有者为root
    group: nginx  # 所属组为nginx
    backup: yes  # 备份原有配置文件

复制目录并控制权限

yaml 复制代码
- name: 复制web静态文件目录到被控节点
  ansible.builtin.copy:
    src: ./html/  # 控制节点的html目录(末尾带/,表示复制目录内内容)
    dest: /var/www/html/  # 被控节点的目标目录
    directory_mode: 0755  # 目录权限755
    mode: 0644  # 目录内文件权限644
    owner: www-data
    group: www-data

复制后验证配置文件

yaml 复制代码
- name: 复制Apache配置并验证语法
  ansible.builtin.copy:
    src: ./files/httpd.conf
    dest: /etc/httpd/conf/httpd.conf
    validate: /usr/sbin/httpd -t -f %s  # 用httpd -t验证配置
  • 复制文件并备份
bash 复制代码
ansible -i hosts data -m copy -a 'src=/etc/hosts dest=/etc/hosts backup=yes'


[root@web01 ~]# ll /etc/hosts*
-rw-r--r-- 1 root root 346 11月 10 15:13 /etc/hosts
-rw-r--r-- 1 root root 311 10月 17 09:06 /etc/hosts.2081.2025-11-10@15:13:21~

systemd服务管理模块

参数 说明 示例取值
name 必选 ,指定服务名称(对应 /usr/lib/systemd/system/ 下的 .service 文件名,可省略 .service 后缀)。 name: nginx(对应 nginx.servicename: sshd.service
state 控制服务的运行状态 (当前是否活跃):- started:启动服务(若未运行则启动,已运行则不操作)。- stopped:停止服务(若运行则停止,已停止则不操作)。- restarted:重启服务(无论当前状态,强制重启)。- reloaded:重新加载服务配置(不中断服务,仅刷新配置,适用于支持 reload 的服务)。 state: started(启动服务)state: reloaded(重载配置)
enabled 控制服务是否开机自启 (系统启动时自动运行):- yes:启用开机自启。- no:禁用开机自启。- masked:屏蔽服务(禁止手动或自动启动,比 no 更严格)。 enabled: yes(开机自启)enabled: no(禁止开机自启)
daemon_reload 当服务配置文件(.service 文件)被修改后,是否重新加载 systemd 守护进程 (使新配置生效):- yes:执行 systemctl daemon-reload。- no:不执行(默认)。 daemon_reload: yes(修改配置后重载)
  • 启动服务
bash 复制代码
systemctl start nginx

ansible -i hosts web -m systemd -a 'name=nginx state=started'
  • 关闭服务
bash 复制代码
systemctl stop nginx


ansible -i hosts web -m systemd -a 'name=nginx state=stopped'
  • 重新服务
bash 复制代码
ansible -i hosts web -m systemd -a 'name=nginx state=restarted'
  • 启动服务并设置开机自启
bash 复制代码
systemctl enable --now nginx

ansible -i hosts web -m systemd -a 'name=nginx enabled=yes state=started'
  • 关闭服务并设置开机不自启
bash 复制代码
sy

ansible -i hosts web -m systemd -a 'name=nginx enabled=no state=stopped'

压缩模块(archive)

参数 说明
path 必选,要压缩的文件 / 目录路径(支持通配符,如 /data/*
dest 必选,输出的压缩包完整路径(如 /tmp/data.tar.gz
format 压缩格式,可选:tar/gz/bz2/xz/zip(默认 tar
compression format=tar 时生效,指定压缩算法:gzip/bzip2/xz/none(默认 gzip
remove 是否删除源文件 / 目录,默认 no(建议保持默认,避免误删)
mode 压缩包的权限(如 0644,需字符串格式)
owner/group 压缩包的属主 / 属组(如 root/root

常用示例

示例 1:打包并压缩为 tar.gz(最常用)

yaml 复制代码
- name: 打包 /data 目录为 /tmp/data.tar.gz
  ansible.builtin.archive:
    path: /data          # 要压缩的目录
    dest: /tmp/data.tar.gz  # 输出的压缩包路径
    format: tar          # 基础格式为tar
    compression: gzip    # 用gzip压缩(最终为tar.gz)
    mode: '0644'         # 压缩包权限
    owner: root
    group: root

示例 2:压缩为 zip 格式

yaml 复制代码
- name: 打包 /var/log/*.log 为 /tmp/logs.zip
  ansible.builtin.archive:
    path: /var/log/*.log  # 匹配多个日志文件
    dest: /tmp/logs.zip
    format: zip           # 直接指定zip格式

传输压缩包并解压(unarchive)

参数 是否必选 默认值 说明 示例
src - 归档文件的源路径。remote_src=yes 时为远程路径;no 时为控制节点路径 远程:/tmp/archive.tar.gz;本地:./local_files.zip
dest - 远程主机上的解压目标目录 /opt/deploy (解压到远程主机的 /opt/deploy 目录)
remote_src yes 控制 src 位置:yes 为远程文件,no 为控制节点文件(需传输) no (表示 src 是控制节点本地文件)
mode - 解压后文件 / 目录的权限(数字或符号格式) 数字:0755;符号:u=rwx,g=rx,o=r
owner - 解压后文件 / 目录的所有者(用户名或 UID) webuser (将文件所有者设为 webuser
group - 解压后文件 / 目录的所属组(组名或 GID) webgroup (将文件所属组设为 webgroup
extra_opts - 传递给底层工具(如 tar/unzip)的额外选项 tar 去顶层目录:--strip-components=1unzip 静默解压:-q
list_files no 若为 yes,仅列出归档内容(不实际解压) yes (仅预览归档中的文件列表,不解压)
creates - 若指定路径存在,则跳过解压(幂等性控制) /opt/deploy/config.ini (若该文件存在,则不解压)
validate_checksum yes 是否验证源文件校验和(确保未篡改),no 则跳过 no (跳过校验和验证,适用于临时文件)
keep_newer no 目标文件比归档中更新时,是否保留目标文件(yes 保留,no 覆盖) yes (保留目标中已更新的文件,不被归档文件覆盖)
exclude - 解压时排除的文件 / 目录(支持通配符) *.tmp (排除所有 .tmp 临时文件);logs/ (排除 logs 目录)

实例 1:从控制节点传输并解压 tar.gz 包到远程主机

场景 :将控制节点本地的 app.tar.gz 传输到远程主机,解压到 /opt/app 目录,同时指定所有者、所属组和权限,并去掉归档文件的顶层目录。

yaml 复制代码
- name: 传输本地tar包并解压到远程主机
  ansible.builtin.unarchive:
    src: ./app.tar.gz  # 控制节点本地文件路径
    dest: /opt/app     # 远程主机目标目录(不存在会自动创建)
    remote_src: no     # 声明src是本地文件(需先传输到远程)
    owner: appuser     # 解压后文件的所有者
    group: appgroup    # 解压后文件的所属组
    mode: '0755'       # 权限设置(所有者读写执行,组和其他读执行)
    extra_opts: '--strip-components=1'  # 去掉tar包的顶层目录(如原结构是app-v1.0/*,解压后直接是/*)
    creates: /opt/app/main.py  # 若main.py已存在,则跳过解压(幂等性控制)

实例 2:解压远程主机上的 zip 文件

场景 :远程主机 /tmp 目录下有 data.zip,将其解压到 /var/data,并排除其中的 .log 临时文件,使用静默模式解压。

yaml 复制代码
- name: 解压远程主机上的zip文件
  ansible.builtin.unarchive:
    src: /tmp/data.zip  # 远程主机上的源文件路径(默认remote_src=yes)
    dest: /var/data     # 远程目标目录
    exclude: '*.log'    # 解压时排除所有.log文件
    extra_opts: '-q'    # 传递给unzip的选项:静默模式(不输出解压过程)
    validate_checksum: no  # 跳过校验和验证(适用于临时生成的zip包)

注意:远程主机需安装 unzip 工具(可通过 package 模块提前安装:name: unzip state: present)。

实例 3:保留目标目录中更新的文件

场景 :远程主机 /backupconfig.tar.bz2,解压到 /etc/config,但如果目标目录中已有比归档文件更新的配置文件,则保留目标文件(不覆盖)。

yaml 复制代码
- name: 解压tar包并保留更新的目标文件
  ansible.builtin.unarchive:
    src: /backup/config.tar.bz2
    dest: /etc/config
    keep_newer: yes  # 若目标文件比归档中文件新,则保留目标文件
    mode: '0644'     # 配置文件权限:所有者读写,组和其他只读

实例 4:仅预览归档文件内容(不解压)

场景 :检查远程主机 /tmp 下的 files.tar.xz 中包含哪些文件,不实际解压。

yaml 复制代码
- name: 预览tar.xz文件中的内容
  ansible.builtin.unarchive:
    src: /tmp/files.tar.xz
    dest: /tmp  # 目标目录仅为占位(实际不解压)
    list_files: yes  # 仅列出内容,不解压
  register: archive_content  # 结果保存到变量

- name: 打印归档文件内容
  ansible.builtin.debug:
    var: archive_content.files  # 输出文件列表

执行后,archive_content.files 会返回归档中的所有文件路径(如 ["file1.txt", "dir/file2.sh"])。

实例 5:解压后递归设置权限(覆盖子文件)

场景 :从控制节点传输 web.tar 到远程 /var/www,解压后强制将所有文件权限设为 0644,目录权限设为 0755(通过 mode 递归生效)。

yaml 复制代码
- name: 解压并递归设置权限
  ansible.builtin.unarchive:
    src: ./web.tar
    dest: /var/www
    remote_src: no
    mode: 
      file: '0644'   # 文件权限
      directory: '0755'  # 目录权限
    owner: www-data  # 所有文件/目录的所有者统一为www-data

替换/添加文件中的内容(lineinfile)单行精准修改

参数 是否必选 默认值 说明 示例
path - 目标文件的路径(远程主机上的路径) path: /etc/nginx/nginx.conf
line - 要添加或替换的行内容(state=present 时有效,state=absent 时无需指定) line: "worker_processes 4;"
regexp - 用于匹配行的正则表达式(若匹配到,则用 line 替换;若未匹配且 state=present,则添加 line regexp: "^worker_processes.*"(匹配以 worker_processes 开头的行)
state present 行的状态:present(确保存在)、absent(删除匹配行) state: absent(删除匹配 regexp 的行)
backrefs no 若为 yes,仅当 regexp 匹配到行时才用 line 替换;若未匹配,不添加 line(默认 no 时未匹配会添加) backrefs: yes(仅替换已有行,不新增)
insertafter EOF regexp 未匹配到行时,在指定行之后插入 lineEOF 表示文件末尾,也可填正则表达式) insertafter: "^http {"(在 http { 行之后插入)
insertbefore - regexp 未匹配到行时,在指定行之前插入 line(用法同 insertafter insertbefore: "^server {"(在 server { 行之前插入)
backup no 是否备份原文件(备份文件会添加 .bak 后缀) backup: yes(修改前备份文件)
regexp_flags None 正则表达式的匹配模式(如 I 表示忽略大小写,M 表示多行模式) regexp_flags: "I"(匹配时忽略大小写)
mode - 设置目标文件的权限(若文件不存在,创建时生效) mode: '0644'

示例 1:修改 Nginx 配置中的工作进程数

需求 :将 /etc/nginx/nginx.confworker_processes 行的值改为 4(若该行不存在则添加到文件末尾)。

yaml 复制代码
- name: 修改 Nginx 工作进程数为 4
  ansible.builtin.lineinfile:
    path: /etc/nginx/nginx.conf
    regexp: "^worker_processes.*"  # 匹配以 worker_processes 开头的行
    line: "worker_processes 4;"    # 替换后的内容
    backup: yes  # 备份原文件

示例 2:确保文件中存在指定的 hosts 解析

需求 :在 /etc/hosts 中添加 192.168.1.100 web01 解析(若已存在则不修改,不存在则添加)。

yaml 复制代码
- name: 添加 hosts 解析
  ansible.builtin.lineinfile:
    path: /etc/hosts
    line: "192.168.1.100 web01"  # 要确保存在的行
    regexp: "^192.168.1.100.*web01"  # 匹配已有的相同解析(避免重复添加)

示例 3:删除配置文件中的注释行

需求 :删除 /etc/sysctl.conf 中所有以 # 开头的注释行(空注释行也删除)。

yaml 复制代码
- name: 删除 sysctl.conf 中的注释行
  ansible.builtin.lineinfile:
    path: /etc/sysctl.conf
    regexp: "^#"  # 匹配以 # 开头的行
    state: absent  # 删除匹配到的行

示例 4:在指定行前插入新配置

需求 :在 /etc/ssh/sshd_configPort 22 行之前,插入 # 自定义SSH端口 注释。

yaml 复制代码
- name: 在 SSH 端口配置前插入注释
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    line: "# 自定义SSH端口"  # 要插入的注释行
    insertbefore: "^Port 22"  # 在 Port 22 行之前插入
    regexp: "^# 自定义SSH端口"  # 避免重复插入

示例 5:仅替换已有行,不新增(backrefs=yes

需求 :若 /etc/profile 中有 export PATH=/usr/local/bin,则替换为 export PATH=/usr/local/bin:/usr/bin;若不存在,则不添加(避免新增多余行)。

yaml 复制代码
- name: 仅替换已有 PATH 配置
  ansible.builtin.lineinfile:
    path: /etc/profile
    regexp: "^export PATH=/usr/local/bin"  # 匹配原始行
    line: "export PATH=/usr/local/bin:/usr/bin"  # 替换后的行
    backrefs: yes  # 仅当 regexp 匹配时才替换,不匹配则不操作

全局替换 (replace)

在 Ansible 中,replace模块(全称为ansible.builtin.replace)是用于在文件中全局替换文本内容 的核心模块,功能类似sed 's/原内容/新内容/g',但更符合 Ansible 的自动化理念(支持幂等性、可维护性更高)。

参数 作用说明
path 必选,目标文件的路径(如/etc/apt/sources.list)。
regexp 必选,用于匹配目标内容的正则表达式(注意转义特殊字符,如.需写为\.)。
replace 必选,替换后的新内容(可引用regexp中的捕获组,如\1代表第一个分组)。
backup 可选,是否备份原文件。值为yes或具体后缀(如.bak),默认不备份。
before 可选,仅替换 "在某行内容之前" 的匹配项(需配合正则)。
after 可选,仅替换 "在某行内容之后" 的匹配项(需配合正则)。
validate 可选,替换后执行命令验证文件有效性(如visudo -cf %s验证 sudoers 文件)。
  1. 基础用法:全局替换文本(如替换 Ubuntu 镜像源)
yaml 复制代码
- name: 替换sources.list中的阿里云镜像
  ansible.builtin.replace:
    path: /etc/apt/sources.list
    regexp: 'cn\.archive\.ubuntu\.com'  # 匹配原镜像地址(.转义为\.)
    replace: 'mirrors.aliyun.com'       # 替换为阿里云镜像
    backup: '.bak'                      # 备份原文件为sources.list.bak
  1. 带正则捕获组的替换(保留部分原有内容)

例如,将配置文件中所有max_size = 1024改为max_size = 2048,但保留变量名:

yaml 复制代码
- name: 调整max_size参数值
  ansible.builtin.replace:
    path: /etc/app/config.ini
    regexp: '(max_size\s*=\s*)1024'  # 捕获组\1保留"max_size = "部分
    replace: '\12048'                # 用\1引用捕获组,替换数值为2048
  1. 限制替换范围(仅替换某段内容中的匹配项)

例如,仅替换[database]配置段后的host = localhosthost = db-server

yaml 复制代码
- name: 仅修改database段的host配置
  ansible.builtin.replace:
    path: /etc/app/config.ini
    regexp: 'host\s*=\s*localhost'
    replace: 'host = db-server'
    after: '\[database\]'  # 仅处理在"[database]"行之后的内容([ ]需转义)

blockinfile(插入多行文本)

blockinfile 是 Ansible 中用于在文件中插入、更新或删除多行文本块 的模块,特别适合处理配置文件中的 "块级内容"(如 Nginx/Apache 的 <VirtualHost> 块、JSON 中的对象、代码中的函数块等)。与处理单行的 lineinfile 不同,blockinfile 能保持多行文本的格式(换行、缩进等),并通过 "标记" 实现幂等性(重复执行不会重复添加)。

参数 作用说明
path/dest 必选,目标文件的路径(如 /etc/nginx/nginx.conf)。
block 必选,要插入的多行文本块(支持 YAML 的 ` ` 保留换行和缩进)。
marker 可选,用于标记文本块的开始和结束(默认值:# {mark} ANSIBLE MANAGED BLOCK)。{mark} 会被替换为 BEGINEND,用于识别块是否已存在(实现幂等)。
insertbefore 可选,指定文本块插入到 "匹配行" 之前(如 ^http { 表示插入到以 http { 开头的行之前)。支持正则表达式。
insertafter 可选,指定文本块插入到 "匹配行" 之后(如 ^events { ... })。
state 可选,present(默认,确保块存在)或 absent(删除块)。
backup 可选,yes 则在修改前备份文件(生成 .bak 后缀的备份)。
trim_empty_lines 可选,yes(默认)则自动去除 block 中首尾的空行。
  1. 基础用法:向文件插入多行配置块

向 Nginx 配置文件中插入 stream 块(4 层负载均衡配置):

yaml 复制代码
- name: 向nginx.conf插入stream块
  blockinfile:
    path: /etc/nginx/nginx.conf
    # 多行内容(用|保留换行和缩进)
    block: |
      stream {
          log_format l4 '$remote_addr [$time_local] "$protocol" $status';
          include /etc/nginx/l4/*.conf;
      }
    # 标记:用于识别该块(避免重复添加)
    marker: "# {mark} ANSIBLE STREAM BLOCK"
    # 插入到http块之前(Nginx要求stream与http同级)
    insertbefore: '^http {'
    backup: yes  # 修改前备份原文件

执行后,nginx.conf 中会新增:

nginx 复制代码
# BEGIN ANSIBLE STREAM BLOCK
stream {
    log_format l4 '$remote_addr [$time_local] "$protocol" $status';
    include /etc/nginx/l4/*.conf;
}
# END ANSIBLE STREAM BLOCK
http {
    ...  # 原有http块内容
}
  1. 更新已存在的块

若再次执行上述任务,且 block 内容有修改(如调整 log_format),blockinfile 会自动更新 BEGINEND 标记之间的内容(不会重复添加)。

  1. 删除指定块

删除之前插入的 stream 块:

yaml 复制代码
- name: 删除nginx.conf中的stream块
  blockinfile:
    path: /etc/nginx/nginx.conf
    marker: "# {mark} ANSIBLE STREAM BLOCK"  # 必须与插入时的marker一致
    state: absent  # 删除块
  1. 在文件末尾插入块

若不指定 insertbefore/insertafter,默认插入到文件末尾:

yaml 复制代码
- name: 在/etc/sysctl.conf末尾添加内核参数块
  blockinfile:
    path: /etc/sysctl.conf
    block: |
      # 自定义内核参数
      net.ipv4.ip_forward = 1
      vm.swappiness = 10
    marker: "# {mark} ANSIBLE SYSCTL BLOCK"

修改定时任务(cron)

Ansible 的cron模块用于管理远程主机的定时任务(crontab) ,支持添加、修改、删除或禁用系统级或用户级的定时任务,无需手动编辑crontab -e

参数 作用 示例值
name 任务的唯一标识(Ansible 通过此名称识别任务,必须唯一) "clean_logs"
job 定时任务要执行的命令或脚本路径(核心内容) "/usr/bin/rm -rf /var/log/*.log"
minute 分钟字段(0-59,*表示每分钟,*/5表示每 5 分钟) "0"(整点)、 "*/10"(每 10 分钟)
hour 小时字段(0-23) "3"(凌晨 3 点)、 "*/6"(每 6 小时)
day 日期字段(1-31) "1"(每月 1 号)
month 月份字段(1-12 或 Jan-Dec) "1,3,5"(1/3/5 月)
weekday 星期字段(0-6 或 Sun-Sat,0 = 周日) "0"(周日)、 "1-5"(周一到周五)
user 指定任务所属的用户(默认是root "www""postgres"
state 任务状态:present(添加 / 修改,默认)、absent(删除) "absent"(删除任务)
disabled 是否禁用任务(yes/no,默认no;禁用后任务前会加#注释) "yes"(禁用任务)
special_time 特殊时间(替代minute/hour/day等字段),如@daily(每天凌晨) "@reboot"(重启后执行)、@weekly

使用示例

以下是常见场景的 playbook 示例:

  1. 添加定时任务(基础示例)

root用户添加 "每天凌晨 3 点清理/var/log日志" 的任务:

yaml 复制代码
- name: 添加日志清理定时任务
  ansible.builtin.cron:
    name: "clean /var/log daily"  # 唯一名称
    minute: "0"                  # 0分
    hour: "3"                    # 3点
    job: "/usr/bin/rm -rf /var/log/*.log > /dev/null 2>&1"  # 执行的命令(重定向输出避免邮件)
    user: root                   # 所属用户(默认root,可省略)
  1. 修改已存在的任务

修改上述任务的执行时间为 "每周日凌晨 3 点",并更新命令:

yaml 复制代码
- name: 修改日志清理任务
  ansible.builtin.cron:
    name: "clean /var/log daily"  # 必须与原任务name一致(通过name匹配)
    minute: "0"
    hour: "3"
    weekday: "0"                  # 0=周日
    job: "/usr/bin/find /var/log -name '*.log' -mtime +7 -delete > /dev/null 2>&1"  # 新命令(删除7天前的日志)
  1. 删除定时任务

删除名称为 "clean /var/log daily" 的任务:

yaml 复制代码
- name: 删除日志清理任务
  ansible.builtin.cron:
    name: "clean /var/log daily"  # 必须匹配要删除的任务名称
    state: absent                 # 状态设为absent表示删除
  1. 禁用 / 启用任务

临时禁用任务(不删除,仅注释):

yaml 复制代码
- name: 禁用日志清理任务
  ansible.builtin.cron:
    name: "clean /var/log daily"
    disabled: yes  # yes=禁用,no=启用(默认)
  1. 使用特殊时间(special_time

添加 "每次系统重启后执行脚本" 的任务:

yaml 复制代码
- name: 重启后执行初始化脚本
  ansible.builtin.cron:
    name: "run init script on reboot"
    special_time: "@reboot"  # 替代minute/hour等字段
    job: "/opt/init.sh"
    user: www  # 以www用户执行

special_time支持的取值:

@reboot(重启后)、@daily(每天凌晨)、@weekly(每周)、@monthly(每月)、@yearly(每年)。

mysql_user(管理数据库用户)

参数 作用说明
name 必需,指定用户名(如rootappuser)。
host 指定用户允许登录的主机(默认localhost),支持通配符:%(所有主机)、192.168.1.%(某网段)。
password 用户密码(明文或加密后的哈希值,推荐用明文,模块会自动加密)。
login_user 连接 MySQL 时使用的用户名(如root,用于执行用户管理操作)。
login_password 连接 MySQL 时的密码(与login_user对应)。
login_unix_socket 通过本地 socket 文件连接(而非网络端口),适用于非默认安装的 MySQL(如/app/data/3306/mysql.sock)。
login_host MySQL 服务器地址(默认localhost,远程连接时需指定)。
login_port MySQL 端口(默认 3306)。
priv 授予的权限,格式:数据库.表:权限1,权限2(如appdb.*:SELECT,INSERT*.*:ALL)。
state 状态:present(创建 / 更新用户,默认)、absent(删除用户)。
append_privs 若为yes,则新增权限而非覆盖原有权限(默认no,会覆盖)。
password_expire 是否强制密码过期(yes/no,默认no)。
相关推荐
秋42711 小时前
ansible剧本
linux·服务器·ansible
码农101号1 天前
Ansible - Role介绍 和 使用playbook部署wordPress
android·ansible
2301_800050993 天前
Ansible
运维·ansible
阎*水5 天前
Ansible 核心要点总结
ansible
小安运维日记5 天前
RHCA - DO374 | Day09:自定义内容集和执行环境
linux·运维·服务器·系统架构·ansible·改行学it
-dcr5 天前
48.Ansible自动化
自动化·ansible·dubbo
神秘面具男036 天前
Ansible Playbook 编写与运行
服务器·网络·ansible
随风语6 天前
ansible
运维·自动化·ansible
tianyuanwo6 天前
纵深防御:构建安全高效的 Ansible 自动化运维体系
运维·安全·ansible