Ansible 常用模块详解文档
一、模块查询与基础语法
(一)模块查询命令
- 查看系统上安装的所有模块:
ansible-doc -l
- 查看指定模块帮助文档(以 ping 模块为例):
ansible-doc ping
(二)基础语法
ansible 主机名称 -m 模块名称 -a '具体命令/参数'
- ansible:核心命令
- 主机名称:指定要操作的受控主机(可在 inventory 文件中定义)
- -m:指定要使用的模块
- 模块名称:具体的模块,如 command、user 等
- -a:指定模块的动作或参数
- 具体命令 / 参数:模块要执行的命令或相关配置参数
(三)执行状态返回信息
- 绿色:执行成功且无需对目标主机做改变
- 黄色:执行成功且对目标主机做了变更
- 红色:执行失败
二、常用模块分类与案例
(一)文件模块
1. copy 模块
用于将本地文件复制到受控主机,支持设置文件权限、所有者、所属组等属性
参数 | 说明 |
---|---|
src | 拷贝本地源文件路径,可使用绝对路径或相对路径;若路径是目录且结尾加 “/”,仅拷贝目录内内容,否则拷贝目录本身及内容 |
dest | 目标路径,必须是绝对路径;若拷贝文件是目录,目标路径也需是目录 |
backup | 是否创建包含时间戳的备份文件,默认为 no,设置为 yes 时会备份原文件 |
force | 是否覆盖远程同名文件,默认为 yes,设置为 no 时忽略同名文件拷贝 |
owner | 设置远程文件的所有者 |
group | 设置远程文件的所属组 |
mode | 设置远程文件权限,可使用数值(如 0644,不能省略第一位)或符号(如 u+rwx、u=rw,g=r,o=r) |
content | 直接以给定字符串或变量值作为文件内容,会替代 src 选项 |
directory_mode | 对目录递归拷贝时,设置此参数仅拷贝新建文件,旧文件不拷贝,默认未设置 |
follow | 是否追踪链接的源文件,可选 yes 或 no |
系统模块
1. user 模块
用于添加、删除和管理用户账户,支持设置用户 UID、密码、所属组等
参数 | 说明 |
---|---|
name | 用户名,必须指定 |
uid | 用户的 UID |
state | 用户状态,present(存在,默认)、absent(删除) |
password | 用户密码,需使用加密后的密码(可通过 openssl passwd 命令生成) |
update_password | 密码更新策略,always(无论用户是否存在都更新密码)、on_create(仅在创建用户时设置密码) |
案例 1:临时命令使用user模块来确保newbie用户存在于node1.example.com上,并且其UID为4000:
[student@master ansible]$ ansible node1 -m user -a 'name=newbie uid=4000 state=present'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 4000,
"home": "/home/newbie",
"name": "newbie",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 4000
}
创建用户并指定密码,如果该用户存在,仍然修改密码:
[student@master ansible]$ openssl passwd -1 linux
$1$w2wT9x2d$fJhcQshqSpftLy4uUXCwU/
[student@master ansible]$ ansible all -m user -a 'name=syf state=present password="$1$FH3V6OOZ$0fxXcgIAEYL3wxtO.5sBA/" update_password=on_create'
创建用户并指定密码,但是如果改用户存在,则不修改密码:
[student@master ansible]$ openssl passwd -1 redhat
$1$aW7u3E0p$zraHPb7Mz/c1oLGjRYWD.1
[student@master ansible]$ ansible all -m user -a 'name=syf1 state=present password="$1$aW7u3E0p$zraHPb7Mz/c1oLGjRYWD.1" update_password=always'
案例2:shell
临时命令使用shell模块来删除node1.example.com节点中的用户newbie:
[student@master ansible]$ ansible node1 -m shell -a 'ls /home'
node1 | CHANGED | rc=0 >>
bob
newbie
student
syf
syf1
[student@master ansible]$ ansible node1 -m shell -a 'userdel -r newbie'
node1 | CHANGED | rc=0 >>
[student@master ansible]$ ansible node1 -m shell -a 'ls /home'
node1 | CHANGED | rc=0 >>
bob
student
syf
syf1
copy 模块
用于将本地文件复制到受控主机,支持设置文件权限、所有者、所属组等属性
参数 | 说明 |
---|---|
src | 拷贝本地源文件路径,可使用绝对路径或相对路径;若路径是目录且结尾加 “/”,仅拷贝目录内内容,否则拷贝目录本身及内容 |
dest | 目标路径,必须是绝对路径;若拷贝文件是目录,目标路径也需是目录 |
backup | 是否创建包含时间戳的备份文件,默认为 no,设置为 yes 时会备份原文件 |
force | 是否覆盖远程同名文件,默认为 yes,设置为 no 时忽略同名文件拷贝 |
owner | 设置远程文件的所有者 |
group | 设置远程文件的所属组 |
mode | 设置远程文件权限,可使用数值(如 0644,不能省略第一位)或符号(如 u+rwx、u=rw,g=r,o=r) |
content | 直接以给定字符串或变量值作为文件内容,会替代 src 选项 |
directory_mode | 对目录递归拷贝时,设置此参数仅拷贝新建文件,旧文件不拷贝,默认未设置 |
follow | 是否追踪链接的源文件,可选 yes 或 no |
案例:将本地 /etc/fstab 文件复制到 node1 主机的 /var/tmp 目录下
[student@master ansible]$ ansible node1 -m copy -a 'src=/etc/fstab dest=/var/tmp/fstab'
[student@master ansible]$ ssh root@node1
Register this system with Red Hat Insights: insights-client --register
Create an account or view all your systems at https://red.ht/insights-dashboard
Last login: Wed Aug 27 11:19:03 2025 from 192.168.122.100
[root@node1 ~]# cd /var/tmp/
[root@node1 tmp]# ls
fstab
案例:复制文件并指定所有者和所属组为 syf
[student@master ansible]$ ansible node1 -m copy -a 'src=/etc/fstab dest=/var/tmp/fstab group=syf owner=syf'
[student@master ansible]$ ansible node1 -m shell -a 'ls -l /var/tmp/fstab'
node1 | CHANGED | rc=0 >>
-rw-r--r--. 1 syf syf 615 Aug 27 19:03 /var/tmp/fstab
template 模块
用法与 copy 模块基本一致,主要用于复制 Jinja2 格式的配置文件,支持变量替换
参数 | 说明 |
---|---|
src | Ansible 控制器上 Jinja2 格式模板的路径,可使用相对或绝对路径 |
dest | 目标路径,必须是绝对路径 |
backup | 是否创建包含时间戳的备份文件,默认为 no |
force | 是否覆盖远程同名文件,默认为 yes,设置为 no 时忽略同名文件拷贝 |
owner | 设置远程文件的所有者 |
group | 设置远程文件的所属组 |
mode | 设置远程文件权限,格式同 copy 模块 |
validate | 复制到目标主机后、放到目标位置前,执行指定命令检查配置文件语法,引用目标文件名用 % s |
file 模块
用于设置文件的权限、所有者、所属组等属性,还可创建文件、目录、链接及删除文件或目录
参数 | 说明 |
---|---|
path | 指定待操作的文件或目录路径,也可用 dest 或 name 替代 |
owner | 设置文件或目录的所有者 |
group | 设置文件或目录的所属组 |
mode | 修改权限,格式可为 0644、u+rwx 或 u=rw,g=r,o=r 等 |
recurse | 是否递归修改文件属性,仅当 state=directory 时生效,默认为 no |
src | 创建链接时指定链接的源文件 |
state | 操作状态:directory(目录不存在则递归创建)、file(文件不存在不创建,默认)、touch(创建新文件或修改文件的 mtime 和 atime)、link(创建或修改软链接)、hard(创建或修改硬链接)、absent(递归删除目录及内容,取消文件或链接) |
setype | 修改文件的 SELinux context 值 |
修改 /var/tmp/fstab 文件的权限、所有者、所属组及 SELinux context 值:
[student@master ansible]$ ansible node1 -m file -a 'path=/var/tmp/fstab mode=g+w mode=o+w group=syf owner=syf setype=samba_share_t'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 4002,
"group": "syf",
"mode": "0646",
"owner": "syf",
"path": "/var/tmp/fstab",
"secontext": "unconfined_u:object_r:samba_share_t:s0",
"size": 615,
"state": "file",
"uid": 4002
}
在 node1 主机上新建 /var/tmp/bbb 文件:
[student@master ansible]$ ansible node1 -m file -a 'path=/var/tmp/bbb state=touch'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"dest": "/var/tmp/bbb",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
在 node1 主机上新建 /var/tmp/cc 目录:
[student@master ansible]$ ansible node1 -m file -a 'path=/var/tmp/cc state=directory'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/var/tmp/cc",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
删除 node1 主机上的 /var/tmp/cc 目录:
[student@master ansible]$ ansible node1 -m file -a 'path=/var/tmp/cc state=absent'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"path": "/var/tmp/cc",
"state": "absent"
}
在 node1 主机上创建 /var/tmp/syf 软链接,指向 /var/tmp/bbb:
[student@master ansible]$ ansible node1 -m file -a 'dest=/var/tmp/syf src=/var/tmp/bbb state=link'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"dest": "/var/tmp/syf",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 12,
"src": "/var/tmp/bbb",
"state": "link",
"uid": 0
}
[root@node1 ~]# cd /var/tmp/
[root@node1 tmp]# ll -Z
total 4
drwxr-xr-x. 2 root root unconfined_u:object_r:user_tmp_t:s0 6 Aug 27 19:54 bbb
drwx------. 3 student student unconfined_u:object_r:user_tmp_t:s0 120 Aug 25 21:18 dnf-student-86fblz_i
-rw-r--rw-. 1 syf syf unconfined_u:object_r:samba_share_t:s0 615 Aug 27 19:03 fstab
lrwxrwxrwx. 1 root root unconfined_u:object_r:user_tmp_t:s0 12 Aug 27 20:19 syf -> /var/tmp/bbb ////
在 node1 主机上创建 /var/tmp/syf 硬链接,指向 /var/tmp/aaa:
[student@master ansible]$ ansible node1 -m file -a 'dest=/var/tmp/syf src=/var/tmp/aaa state=hard'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"dest": "/var/tmp/syf/aaa",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 0,
"src": "/var/tmp/aaa",
"state": "hard",
"uid": 0
}
yum_repository 模块
用于配置 yum 仓库,可添加或删除 yum 仓库配置
参数 | 说明 |
---|---|
name | 仓库名称,需保证唯一性 |
baseurl | 仓库的 baseurl 地址 |
mirrorlist | 仓库的 mirrorlist 地址 |
description | 仓库的描述信息 |
enabled | 是否启用该仓库,默认为 yes |
file | 保存仓库配置的文件名,不设置则默认以 name 命名,自动加 “.repo” 后缀 |
gpgcheck | 是否进行 gpgcheck,可选 yes 或 no |
gpgkey | gpgkey 的地址 |
reposdir | 保存.repo 文件的目录,默认 /etc/yum.repos.d/ |
state | repo 文件的状态,present(存在,默认)、absent(删除) |
在node1主机上配置 BASE 仓库,文件名为 syf.repo:
[student@master ansible]$ ansible node1 -m yum_repository -a 'file=syf name=aa description=aa1 baseurl=http://ansible.example.com/rhel9/BaseOS enabled=yes gpgcheck=no'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"repo": "aa",
"state": "present"
}
在node1主机上配置 STREAM 仓库,文件名为 syf1.repo:
[student@master ansible]$ ansible node1 -m yum_repository -a 'file=syf1 name=cc description=cc1 baseurl=http://ansible.example.com/rhel9/AppStream enabled=yes gpgcheck=no'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"repo": "cc",
"state": "present"
}
[student@master ansible]$ ansible node1 -m shell -a 'cat /etc/yum.repos.d/syf.repo'
yum 模块
使用 yum 软件包管理器管理软件包,支持安装、卸载、更新软件包
参数 | 说明 |
---|---|
name | 指定要操作的包名,可带版本号,多个包用逗号分隔 |
state | 操作状态:present、installed、latest(用于安装包);absent、removed(用于卸载包) |
disable_gpg_check | 安装包时是否禁止 gpgcheck,仅在 state=present 或 latest 时生效 |
disablerepo | 禁用指定的仓库 ID,多个用逗号分隔 |
enablerepo | 明确使用指定的仓库 ID |
exclude | 排除不安装的包,仅在 state=present 或 latest 时生效 |
list | 类似 yum list 命令,查看包状态 |
update_cache | 是否强制更新 yum 的缓存 |
在node1主机上安装 httpd 服务:
[student@master ansible]$ ansible node1 -m yum -a 'name=httpd state=present'
在node1主机上卸载 httpd 服务:
[student@master ansible]$ ansible node1 -m yum -a 'name=httpd state=removed'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Removed: httpd-2.4.53-7.el9.x86_64"
]
}
service 模块
用于管理系统服务,支持启动、停止、重启服务及设置服务开机自启动。
参数 | 说明 |
---|---|
name | 服务名,必须指定 |
state | 服务状态:started(启动服务,幂等操作)、stopped(停止服务,幂等操作)、restarted(重启服务)、reloaded(重新加载配置文件,服务未运行则启动) |
enabled | 是否设置服务开机自启动,默认为 no |
案例:在node1主机上启动httpd服务,并设置开机自启动:
[student@master ansible]$ ansible node1 -m service -a 'name=httpd state=started enabled=yes'
fetch 模块
与 copy 模块工作方式相反,从远程主机拉取文件到本地,存储时以主机名作为目录树,仅支持拉取文件,不支持目录
参数 | 说明 |
---|---|
src | 远程主机上的源文件路径,只能是文件,不支持目录 |
dest | 本地存储拉取文件的目录,如 dest=/data,src=/etc/fstab,远程主机名为host.exp.com,则保存路径为 /data/host.exp.com/etc/fstab |
fail_on_missing | 源文件不存在时任务是否失败,默认为 no,设置为 yes 时失败 |
flat | 改变拉取后路径存储方式,设置为 yes 且 dest 以 “/” 结尾时,直接将源文件的 basename 存储在 dest 下,需注意多主机拉取时文件覆盖问题 |
validate_checksum | 拉取文件后是否检查 md5 与源文件是否一致 |
将所有远程主机的 /etc/fstab 文件拉取到本地 /tmp 目录,存储路径为 /tmp/ 主机名 /etc/fstab:
[student@master ansible]$ ansible all -m fetch -a 'scr=/etc/fstab dest=/tmp'
将 node1 主机的 /etc/fstab 文件拉取到本地 /tmp 目录,存储名为 /tmp/fstab:
[student@master ansible]$ ansible node1 -m fetch -a 'src=/etc/fstab dest=/tmp/ flat=yes'
将所有远程主机的 /etc/fstab 文件拉取到本地 /tmp 目录,存储名为 /tmp/fstab - 主机名:
[student@master ansible]$ ansible all -m fetch -a 'src=/etc/fstab dest=/tmp/fstab-{{inventory_hostname}} flat=yes'
firewalld 模块
使用 firewalld 管理防火墙规则,支持配置端口、服务及富规则
参数 | 说明 |
---|---|
service | 指定服务名(如 http、ssh) |
permanent | 是否永久生效,默认为 no,设置为 yes 时规则永久保存 |
state | 规则状态:enabled(启用规则)、disabled(禁用规则) |
immediate | 是否立即生效,默认为 no,设置为 yes 时规则立即应用 |
zone | 指定防火墙区域,默认 public |
rich_rule | 指定富规则,用于更精细的访问控制 |
允许所有主机的 http 流量传入,规则永久且立即生效:
[student@master ansible]$ ansible all -m firewalld -a 'service=http permanent=yes state=enabled immediate=yes'
允许 192.168.100.0/24 网段主机的 http 流量传入,规则永久且立即生效:
[student@master ansible]$ ansible all -m firewalld -a 'zone=public rich_rule="rule family=ipv4 source address=192.168.100.0/24 service name=http accept" permanent=yes state=enabled immediate=yes'
replace 模块
根据指定正则表达式替换文件中的字符串,文件中所有匹配的字符串都会被替换
参数 | 说明 |
---|---|
path | 操作的文件路径,2.3 版本前可用 dest、destfile、name,2.4 版本后可混用 |
regexp | Python 正则表达式,匹配要替换的字符串,必须指定 |
replace | 替换后的字符串 |
backup | 是否在修改前备份文件,建议设置为 yes |
将/tmp/syf中的“ab”替换为“ss”:
[root@node1 tmp]# touch syf
[root@node1 tmp]# vi syf
abc acd ads sad
ccc ab cda aaa
~
[student@master ansible]$ ansible node1 -m replace -a 'path=/tmp/syf regexp="ab" replace="ss"'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"msg": "2 replacements made",
"rc": 0
}
[student@master ansible]$ ansible node1 -m shell -a 'cat /tmp/syf'
node1 | CHANGED | rc=0 >>
ssc acd ads sad
ccc ss cda aaa
[root@node1 tmp]# cat syf
ssc acd ads sad
ccc ss cda aaa
将/tmp/syf文件中的“ss”替换成“xx”,且把替换前的/tmp/syf文件备份:
[student@master ansible]$ ansible node1 -m replace -a 'path=/tmp/syf regexp=ss replace=xx backup=yes'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"backup_file": "/tmp/syf.1390.2025-08-29@10:35:11~",
"changed": true,
"msg": "2 replacements made",
"rc": 0
}
[student@master ansible]$ ansible node1 -m shell -a 'cat /tmp/syf'
node1 | CHANGED | rc=0 >>
xxc acd ads sad
ccc xx cda aaa
[root@node1 ~]# cd /tmp/
[root@node1 tmp]# cat syf
xxc acd ads sad
ccc xx cda aaa
[root@node1 tmp]# ls
syf
syf.1390.2025-08-29@10:35:11~
[root@node1 tmp]# cat syf.1390.2025-08-29@10\:35\:11~
ssc acd ads sad
ccc ss cda aaa
parted模块:
新建扩展分区:
新建逻辑分区:
filesystem—文件系统:
mount—挂载:
案例:新建一个分区大小为500MiB,格式化为xfs的文件系统,并挂载到/test1目录下
[student@master ansible]$ ansible node3 -m parted -a 'device=/dev/vdb number=1 part_type=primary part_start=10MiB part_end=510MiB state=present'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"disk": {
"dev": "/dev/vdb",
"logical_block": 512,
"model": "Virtio Block Device",
"physical_block": 512,
"size": 20971520.0,
"table": "msdos",
"unit": "kib"
},
"partitions": [
{
"begin": 10240.0,
"end": 522240.0,
"flags": [],
"fstype": "",
"name": "",
"num": 1,
"size": 512000.0,
"unit": "kib"
}
],
"script": "unit KiB mklabel msdos mkpart primary 10MiB 510MiB"
}
[student@master ansible]$ ssh root@node3
[root@node3 ~]# parted -l
Model: Virtio Block Device (virtblk)
Disk /dev/vdb: 21.5GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 10.5MB 535MB 524MB primary
Model: Virtio Block Device (virtblk)
Disk /dev/vda: 21.5GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 1075MB 1074MB primary xfs boot
2 1075MB 3222MB 2147MB primary linux-swap(v1) swap
3 3222MB 21.5GB 18.3GB primary xfs
[root@node3 ~]# parted /dev/vdb
GNU Parted 3.5
Using /dev/vdb
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit
Unit? [compact]? MiB
(parted) p
Model: Virtio Block Device (virtblk)
Disk /dev/vdb: 20480MiB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 10.0MiB 510MiB 500MiB primary
(parted)
[student@master ansible]$ ansible node3 -m filesystem -a 'dev=/dev/vdb1 fstype=xfs'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true
}
[student@master ansible]$ ansible node3 -m file -a 'path=/test1 state=directory'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/test1",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
[student@master ansible]$ ansible node3 -m shell -a 'blkid /dev/vdb1'
node3 | CHANGED | rc=0 >>
/dev/vdb1: UUID="70032a34-cd55-4e1b-98cd-5ef225d5f313" TYPE="xfs" PARTUUID="f86c93d6-01" //查看/dev/vdb1的UUID
[student@master ansible]$ ansible node3 -m mount -a 'src="UUID=70032a34-cd55-4e1b-98cd-5ef225d5f313" path=/test1 fstype=xfs state=mounted' //将分区/dev/vdb1挂载到/common目录
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"backup_file": "",
"boot": "yes",
"changed": true,
"dump": "0",
"fstab": "/etc/fstab",
"fstype": "xfs",
"name": "/test1",
"opts": "defaults",
"passno": "0",
"src": "UUID=70032a34-cd55-4e1b-98cd-5ef225d5f313"
}
[student@master ansible]$ ansible node3 -m shell -a 'df -Th'
node3 | CHANGED | rc=0 >>
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs tmpfs 985M 0 985M 0% /dev/shm
tmpfs tmpfs 394M 5.6M 389M 2% /run
/dev/vda3 xfs 17G 1.4G 16G 8% /
/dev/vda1 xfs 1014M 182M 833M 18% /boot
/dev/vdb1 xfs 495M 29M 466M 6% /test1
tmpfs tmpfs 197M 0 197M 0% /run/user/1000
卸载:
ansible node3 -m mount -a 'path=/test1 src="UUID=70032a34-cd55-4e1b-98cd-5ef225d5f313" fstype=xfs state=absent'
lvg—新建卷组:
lvol—新建逻辑卷:
案例:创建一个逻辑卷lv0,大小为1000M,格式化为ext4的文件系统,并挂载到/test2目录下
[student@master ansible]$ ansible node3 -m parted -a 'device=/dev/vdb number=2 part_type=primary part_start=520MiB part_end=2520MiB state=present'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"disk": {
"dev": "/dev/vdb",
"logical_block": 512,
"model": "Virtio Block Device",
"physical_block": 512,
"size": 20971520.0,
"table": "msdos",
"unit": "kib"
},
"partitions": [
{
"begin": 10240.0,
"end": 522240.0,
"flags": [],
"fstype": "xfs",
"name": "",
"num": 1,
"size": 512000.0,
"unit": "kib"
},
{
"begin": 532480.0,
"end": 2580480.0,
"flags": [],
"fstype": "",
"name": "",
"num": 2,
"size": 2048000.0,
"unit": "kib"
}
],
"script": "unit KiB mkpart primary 520MiB 2520MiB"
}
[student@master ansible]$ ansible node3 -m yum -a 'name=lvm2 state=present'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Installed: lvm2-9:2.03.16-3.el9.x86_64",
"Installed: libaio-0.3.111-13.el9.x86_64",
"Installed: device-mapper-9:1.02.185-3.el9.x86_64",
"Installed: device-mapper-event-9:1.02.185-3.el9.x86_64",
"Installed: device-mapper-event-libs-9:1.02.185-3.el9.x86_64",
"Installed: device-mapper-libs-9:1.02.185-3.el9.x86_64",
"Installed: lvm2-libs-9:2.03.16-3.el9.x86_64",
"Installed: device-mapper-persistent-data-0.9.0-13.el9.x86_64",
"Removed: device-mapper-9:1.02.187-7.el9.x86_64",
"Removed: device-mapper-libs-9:1.02.187-7.el9.x86_64"
]
}
[student@master ansible]$ ansible node3 -m lvg -a 'vg=vg0 pvs=/dev/vdb2'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true
}
[student@master ansible]$ ansible node3 -m lvol -a 'vg=vg0 lv=lv0 size=1000'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"msg": ""
}
[root@node3 ~]# lvdisplay
--- Logical volume ---
LV Path /dev/vg0/lv0
LV Name lv0
VG Name vg0
LV UUID DOL3tY-hsTA-Bp0g-YWfQ-zUy1-U3Jv-Z1TCPY
LV Write Access read/write
LV Creation host, time node3.example.com, 2025-08-29 14:34:35 +0800
LV Status available
# open 0
LV Size 1000.00 MiB
Current LE 250
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 252:0
[student@master ansible]$ ansible node3 -m filesystem -a 'dev=/dev/vg0/lv0 fstype=ext4'
[student@master ansible]$ ansible node3 -m file -a 'path=/test2 state=directory'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/test2",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
[student@master ansible]$ ansible node3 -m shell -a 'blkid'
node3 | CHANGED | rc=0 >>
/dev/vdb2: UUID="yJyLdE-jbYF-bcTN-ysdP-nvbx-Hb2u-3Gn0EQ" TYPE="LVM2_member" PARTUUID="f86c93d6-02"
/dev/vdb1: UUID="70032a34-cd55-4e1b-98cd-5ef225d5f313" TYPE="xfs" PARTUUID="f86c93d6-01"
/dev/mapper/vg0-lv0: UUID="bde15072-e0a5-40a4-82c1-6ded75c7a237" TYPE="ext4"
/dev/vda2: UUID="ac484e0f-e75c-4224-a859-051933d99f97" TYPE="swap" PARTUUID="5e589421-02"
/dev/vda3: UUID="846b713a-b686-49cc-a291-8014e6c4cb39" TYPE="xfs" PARTUUID="5e589421-03"
/dev/vda1: UUID="6c62ede3-40ae-4057-84f0-7a8b254a73ae" TYPE="xfs" PARTUUID="5e589421-01"
[student@master ansible]$ ansible node3 -m mount -a 'src="UUID=bde15072-e0a5-40a4-82c1-6ded75c7a237" path=/test2 fstype=ext4 state=mounted'
node3 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"backup_file": "",
"boot": "yes",
"changed": true,
"dump": "0",
"fstab": "/etc/fstab",
"fstype": "ext4",
"name": "/test2",
"opts": "defaults",
"passno": "0",
"src": "UUID=bde15072-e0a5-40a4-82c1-6ded75c7a237"
}
[student@master ansible]$ ansible node3 -m shell -a 'df -Th'
node3 | CHANGED | rc=0 >>
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs tmpfs 985M 0 985M 0% /dev/shm
tmpfs tmpfs 394M 5.6M 389M 2% /run
/dev/vda3 xfs 17G 1.4G 16G 9% /
/dev/vdb1 xfs 495M 29M 466M 6% /test1
/dev/vda1 xfs 1014M 182M 833M 18% /boot
tmpfs tmpfs 197M 0 197M 0% /run/user/1000
/dev/mapper/vg0-lv0 ext4 966M 24K 900M 1% /test2
在线扩展逻辑卷:
ansible node1 -m lvol -a 'lv=lv0 size=1600M vg=vg0 resizefs=yes'
debug:
用户输出自定义的信息,类似于echo、print等输出命令。ansible中的debug主要用于输出变量值、表达式值,以及用于when条件判断时。使用方式非常简单
参数名 | 作用与规则 |
---|---|
msg |
输出自定义文本 / 变量拼接内容(支持 {{ 变量 }} 插值);若内容为空,默认输出基础字符。 |
var |
直接指定待调试的变量名(禁止加 {{ }}),仅输出变量的值(如 var: my_var )。 |
verbosity |
控制调试信息的输出级别(接受数字 N );仅当 Ansible 运行时的 verbosity(如 ansible-playbook -v 层级)≥ N 时,才显示该信息。 |
[student@master ansible]$ echo 123
123
[student@master ansible]$ ansible node1 -m debug -a 'msg=syf'
node1 | SUCCESS => {
"msg": "syf"
}
[student@master ansible]$ vim a.yml
---
- name: test
hosts: node2
tasks:
- name: a
debug:
msg: "{{ ansible_fqdn }}"
~
[student@master ansible]$ ansible-playbook a.yml
PLAY [test] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [node2]
TASK [a] ***********************************************************************
ok: [node2] => {
"msg": "node2.example.com"
}
PLAY RECAP *********************************************************************
node2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[student@master ansible]$ ansible node1 -m debug -a 'msg="this is {{ inventory_hostname }}"'
node1 | SUCCESS => {
"msg": "this is node1"
}
cron—计划任务模块:
参数名 | 详细说明 |
---|---|
backup |
- 类型:yes/no - 作用:修改远程 cron_file 前,备份原有文件 |
cron_file |
- 作用:自定义 cron 配置文件名(相对路径默认存于 /etc/cron.d ),必须配合 user 参数使用 |
user |
- 作用:指定修改哪个用户的 crontab (默认修改 root 用户的定时任务) |
disabled |
- 作用:禁用 crontab 中的某个任务,需配合 state=present 使用 |
env |
- 类型:yes/no - 作用:在 crontab 顶端添加环境变量,通过 name (变量名)和 job (变量值)定义 |
job |
- 作用:定时任务要执行的命令;若启用 env ,则 job 表示环境变量的值(等价 value="xxx" ),需配合 state=present |
minute |
- 格式:0-59 、* 、*/N (如 */5 表示每 5 分钟) - 默认值:* (每分钟) |
hour |
- 格式:0-23 、* 、*/N - 默认值:* (每小时) |
day |
- 格式:1-31 、* 、*/N - 默认值:* (每天) |
month |
- 格式:1-12 、* 、*/N - 默认值:* (每月) |
weekday |
- 格式:0-6 (0 = 周日,6 = 周六)、* - 默认值:* (每周每天) |
name |
- 作用:描述定时任务的字符串;若配置 env ,则 name 为环境变量名,需配合 state=absent; 若未设 name 且 state=present ,即使已有同名任务也会新建 |
special_time |
- 有效值:reboot (重启后)、hourly (每小时)、daily (每天)等,用于简化定时规则 |
state |
- 可选值:present (默认,创建任务 / 环境变量)、absent (移除任务 / 环境变量) |
[student@master ansible]$ ansible node1 -m user -a 'name=natasha state=present'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1001,
"home": "/home/natasha",
"name": "natasha",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1001
}
[student@master ansible]$ ansible node1 -m cron -a 'name=lq1 user=natasha minute="*/5" job="logger RH200 Test"'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"envs": [],
"jobs": [
"lq1"
]
}
[student@master ansible]$ ansible node1 -m cron -a 'name=lq2 user=natasha minute=28 hour=14 job="logger RH200 Test"'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"envs": [],
"jobs": [
"lq1",
"lq2"
]
}
[student@master ansible]$ ansible node1 -m shell -a 'crontab -l -u natasha'
node1 | CHANGED | rc=0 >>
#Ansible: lq1
*/5 * * * * logger RH200 Test
#Ansible: lq2
28 14 * * * logger RH200 Test
get_url模块:
get_url
模块用于从 HTTP、HTTPS 或 FTP 协议的源,向目标节点下载文件,助力自动化部署、资源同步等场景,比如拉取配置文件、软件安装包到节点
参数名 | 功能与使用规则 | ||
---|---|---|---|
backup |
下载文件时,若启用(设为 yes 等有效值 ),会额外创建含时间戳的备份文件,用于保留历史版本对比 。 |
||
dest |
必选,指定文件保存的绝对路径。若路径是目录,以 URL 中的基础文件名(如 http://example.com/file.txt 取 file.txt )作为保存名;若为目录,force 参数部分规则不生效 。 |
||
force |
控制下载覆盖逻辑。dest 是目录时,总下载但仅文件变化才替换;dest 非目录且设为 yes ,总下载但仅文件变化才替换;默认 no ,仅目标路径无文件时下载 。 |
||
tmp_dest |
临时存放下载文件的目录,任务执行完会自动删除临时文件,用于规避目标路径权限等问题 。 | ||
group |
设定下载后文件 / 目录所属的用户组,需目标系统用户组存在 。 | ||
owner |
设定下载后文件 / 目录的所有者,需目标系统用户存在 。 | ||
mode |
配置文件 / 目录权限,支持数字权限(如 0644 )、符号权限(如 u+rwx )格式,遵循 Linux 权限规则 。 |
||
timeout |
设置请求 URL 的超时时间,单位秒,默认 10 秒,网络不稳定场景可调整 。 | ||
url |
必选,待下载资源的 URL ,支持 http /https /ftp 协议(格式:`(http |
https | ftp)😕/[user[:pass]]@host.domain[:port]/path );也支持 file协议(如 file:///path/to/file` )实现本地文件复制 。 |
[root@ansible ~]# cd /tmp/
[root@ansible tmp]# cd /var/www/html/
[root@ansible html]# ls
ansible-automation-platform materials rhel9 roles
[root@ansible html]# echo 123 > file1
[root@ansible html]# ls
ansible-automation-platform file1 materials rhel9 roles
[student@master ansible]$ ansible node1 -m get_url -a 'url=http://ansible.example.com/syf dest=/tmp/'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"checksum_dest": "fbbe2adbce22a7cc5904e75d294a41f11fa67ebf",
"checksum_src": "a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0",
"dest": "/tmp/syf",
"elapsed": 0,
"gid": 0,
"group": "root",
"md5sum": "ba1f2511fc30423bdbb183fe33f3dd0f",
"mode": "0644",
"msg": "OK (4 bytes)",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 4,
"src": "/home/student/.ansible/tmp/ansible-tmp-1756452496.2627316-1373-98499907067545/tmpx7kf81em",
"state": "file",
"status_code": 200,
"uid": 0,
"url": "http://ansible.example.com/syf"
}
[root@node1 ~]# cd /tmp/
[root@node1 tmp]# cat syf
123
[student@master ansible]$ ansible node1 -m get_url -a 'url=http://ansible.example.com/syf dest=/tmp/syf1'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"checksum_dest": null,
"checksum_src": "a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0",
"dest": "/tmp/syf1",
"elapsed": 0,
"gid": 0,
"group": "root",
"md5sum": "ba1f2511fc30423bdbb183fe33f3dd0f",
"mode": "0644",
"msg": "OK (4 bytes)",
"owner": "root",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 4,
"src": "/home/student/.ansible/tmp/ansible-tmp-1756452720.4422228-1390-9744034934702/tmpcza3pt3a",
"state": "file",
"status_code": 200,
"uid": 0,
"url": "http://ansible.example.com/syf"
}
[root@node1 tmp]# cat syf1
123
[root@ansible ~]# cd /var/www/html/
[root@ansible html]# echo 123 > syf1
[root@ansible html]# vim syf1
1234
~
[student@master ansible]$ ansible node1 -m get_url -a 'url=http://ansible.example.com/syf1 dest=/tmp/syf1'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"checksum_dest": "a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0",
"checksum_src": "1be168ff837f043bde17c0314341c84271047b31",
"dest": "/tmp/syf1",
"elapsed": 0,
"gid": 0,
"group": "root",
"md5sum": "e7df7cd2ca07f4f1ab415d457a6e1c13",
"mode": "0644",
"msg": "OK (5 bytes)",
"owner": "root",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 5,
"src": "/home/student/.ansible/tmp/ansible-tmp-1756453541.4014435-1539-221617614588321/tmp1keb9_dc",
"state": "file",
"status_code": 200,
"uid": 0,
"url": "http://ansible.example.com/syf1"
}
[root@node1 tmp]# cat syf1
1234
[root@ansible html]# ls
ansible-automation-platform materials rhel9 roles syf syf1
[root@ansible html]# ll
total 16
drwxr-xr-x. 4 root root 55 Aug 25 19:55 ansible-automation-platform
drwxr-xr-x. 2 root root 4096 Aug 25 19:55 materials
drwxr-xr-x. 7 root root 4096 Aug 25 19:57 rhel9
drwxr-xr-x. 4 root root 70 Aug 25 19:57 roles
-rw-r--r-- 1 root root 4 Aug 29 15:27 syf
-rw-r--r-- 1 root root 5 Aug 29 15:44 syf1
[root@ansible html]# ls /home/
student
[root@ansible html]# chgrp student syf1
[student@master ansible]$ ansible node1 -m get_url -a 'url=http://ansible.example.com/syf1 dest=/tmp/syf1'
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"dest": "/tmp/syf1",
"elapsed": 0,
"gid": 0,
"group": "root",
"mode": "0644",
"msg": "HTTP Error 304: Not Modified",
"owner": "root",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 5,
"state": "file",
"status_code": 304,
"uid": 0,
"url": "http://ansible.example.com/syf1"
}
[root@node1 ~]# mkdir /share
[root@node1 ~]# cd /share/
[root@node1 share]# touch syf1
[root@node1 share]# ls -ldZ /share/
drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 18 Aug 29 15:52 /share/
[root@node1 share]# ll /share/
total 0
-rw-r--r--. 1 root root 0 Aug 29 15:52 syf1
[student@master ansible]$ ansible node1 -m sefcontext -a 'target="/share(/.*)?" setype=samba_share_t state=present'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"ftype": "a",
"serange": "s0",
"setype": "samba_share_t",
"seuser": "system_u",
"state": "present",
"target": "/share(/.*)?"
}
[student@master ansible]$ ansible node1 -m shell -a 'restorecon -Rv /share'
node1 | CHANGED | rc=0 >>
Relabeled /share from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:samba_share_t:s0
Relabeled /share/syf1 from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:samba_share_t:s0
[root@node1 share]# ll -ldZ /share/
drwxr-xr-x. 2 root root unconfined_u:object_r:samba_share_t:s0 18 Aug 29 15:52 /share/
[student@master ansible]$ ansible node1 -m file -a 'path=/www/index.html setype=httpd_sys_content_t'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/www/index.html",
"secontext": "unconfined_u:object_r:httpd_sys_content_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
[root@node1 www]# ll -Z index.html
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 0 Aug 29 16:10 index.html