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)。
相关推荐
有毒的教程10 小时前
Ansible批量操作自动化完整教程:批量部署服务、配置同步、软件更新实战
运维·自动化·ansible
Hy行者勇哥5 天前
用Cursor智能编写Ansible/Terraform脚本,打通CI/CD链路
ci/cd·ansible·terraform
芷栀夏7 天前
飞牛NAS怎么部署Immich?家庭照片自动备份与远程访问教程
服务器·nginx·ansible
悠然南风18 天前
Ansible常见模块总结及LDAP Role 编写与调试
ansible
祺风挽楠1 个月前
ansible编辑
网络·ansible
芳心粽伙饭1 个月前
Ansible课后作业
ansible
烁3471 个月前
Ansible初识
ansible
烁3471 个月前
Ansible安装部署调试
ansible
烁3471 个月前
Ansible命令
ansible
小义_1 个月前
【Ansible】(三)基础配置与连接设置
云原生·ansible