Ansible 临时命令与常用模块实操指南
Ansible 临时命令与常用模块使用
Ansible 临时命令(Ad-hoc 模式)通过调用不同模块执行单条任务,适用于临时性操作。以下是模块查询方法、核心模块语法及实操案例,覆盖用户管理、文件操作、软件部署等常见场景。
一、模块查询基础
1. 查看系统已安装的所有模块
ansible-doc -l
2. 查看指定模块的帮助文档(以 ping
为例)
# 查看模块参数、用法及示例[root@master ~]# ansible-doc ping> ANSIBLE.BUILTIN.PING (/usr/lib/python3.9/site-packages/ansible/modules/ping.p> A trivial test module, this module always returns `pong\' on successful contact. It does not make sense in playbooks, but it is useful from `/usr/bin/ansible\' to verify the ability to login and that a usable Python is configured. This is NOT ICMP ping, this is just a trivial test module that requires Python on the remote-node. For Windows targets, use the [ansible.windows.win_ping] module instead. For Network targets, use the [ansible.netcommon.net_ping] module instead.ADDED IN: historicalOPTIONS (= is mandatory):- data Data to return for the `ping\' return value. If this parameter is set to `crash\', the module will cause an/EXA #查看示例EXAMPLES:# Test we can logon to \'webservers\' and execute python with json lib.# ansible webservers -m ansible.builtin.ping- name: Example from an Ansible Playbook ansible.builtin.ping:- name: Induce an exception to see what happens ansible.builtin.ping: data: crashRETURN VALUES:- ping Value provided with the data parameter. returned: success
二、临时命令语法格式
ansible <主机/分组> -m <模块名> -a \'\'# :Inventory 中定义的主机名或分组名(如 node1、all)# -m :指定要调用的模块(如 user、copy)# -a \'\':模块的具体配置(键值对格式,空格分隔)
执行结果状态说明
- 绿色:执行成功,目标主机无变更;
- 黄色:执行成功,目标主机产生变更(如新建用户、修改文件);
- 红色:执行失败(如参数错误、权限不足)。
三、常用模块实操案例
(一)用户管理模块:user
用于添加、删除、修改用户账户及属性。
name
name=newbie
)uid
uid=400
),需确保唯一性state
present
(创建 / 保留用户,默认)、absent
(删除用户)password
openssl passwd -1
生成的密文)update_password
always
(始终更新)、on_create
(仅创建时设置,默认)create_home
yes
(默认)、no
shell
shell=/bin/bash
,默认随系统配置)group
group=zhang3
)在 node1
上创建用户 newbie
,指定 UID=400:
[student@master ansible]$ ansible node1 -m user -a \'name=newbie uid=400 state=present\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"comment\": \"\", \"create_home\": true, \"group\": 1001, \"home\": \"/home/newbie\", \"name\": \"newbie\", \"shell\": \"/bin/bash\", \"state\": \"present\", \"stderr\": \"useradd warning: newbie\'s uid 400 outside of the UID_MIN 1000 and UID_MAX 60000 range.\\n\", \"stderr_lines\": [ \"useradd warning: newbie\'s uid 400 outside of the UID_MIN 1000 and UID_MAX 60000 range.\" ], \"system\": false, \"uid\": 400}
创建用户 zhang3
,指定密码(若用户存在则仅更改密码):
# 需要使用加密密码[student@master ansible]$ openssl passwd -1 123$1$NjRojGFn$y4oEdLR3M8PQvnPLqX2al1[student@master ansible]$ ansible node1 -m user -a \'name=zhang3 state=present password=\"$1$NjRojGFn$y4oEdLR3M8PQvnPLqX2al1\" update_password=always\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"comment\": \"\", \"create_home\": true, \"group\": 1002, \"home\": \"/home/zhang3\", \"name\": \"zhang3\", \"password\": \"NOT_LOGGING_PASSWORD\", \"shell\": \"/bin/bash\", \"state\": \"present\", \"system\": false, \"uid\": 1001}
创建用户 zhang3
,指定密码(若用户存在不对密码做更改)
[student@master ansible]$ openssl passwd -1 555$1$qfOdfqaN$.cPyVgM/72j/uDUCvAj270[student@master ansible]$ ansible node1 -m user -a \'name=zhang3 password=\"$1$qfOdfqaN$.cPyVgM/72j/uDUCvAj270\" update_password=on_create\'node1 | SUCCESS => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"append\": false, \"changed\": false, \"comment\": \"\", \"group\": 1002, \"home\": \"/home/zhang3\", \"move_home\": false, \"name\": \"zhang3\", \"password\": \"NOT_LOGGING_PASSWORD\", \"shell\": \"/bin/bash\", \"state\": \"present\", \"uid\": 1001}
(二)命令执行模块:shell
执行远程主机的 Shell 命令(支持管道、重定向等复杂语法)。
args
/ 直接跟命令a=\'userdel -r newbie\'
,删除用户及家目录)chdir
chdir=/tmp
)creates
creates=/aaa/file1
)removes
removes=/aaa/file1
)在 node1
上删除用户 newbie
(含家目录);
[student@master ansible]$ ansible node1 -m shell -a \'userdel -r newbie\'node1 | CHANGED | rc=0 >>
(三)文件复制模块:copy
将本地文件复制到远程主机,并可指定权限、所有者。
src
src=/etc/fstab
)dest
dest=/var/tmp/fstab
)owner
owner=zhang3
)group
group=root
)mode
mode=0644
,八进制格式,需加前导 0)backup
yes
(备份为 dest.xxx~
)、no
(默认)content
src
,如 content=\"hello\"
生成含 hello 的文件)将本地 /etc/fstab
复制到远程 用户node2的 /var/tmp/fstab
:
[student@master ansible]$ ansible node2 -m copy -a \'src=/etc/fstab dest=/var/tmp/fstab\'node2 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/var/tmp/fstab\", \"gid\": 0, \"group\": \"root\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"mode\": \"0644\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:user_home_t:s0\", \"size\": 579, \"src\": \"/home/student/.ansible/tmp/ansible-tmp-1756266300.572999-1419-214666091543219/source\", \"state\": \"file\", \"uid\": 0}
复制文件到node1并指定所有者为 zhang3
、所属组为 zhang3
:
[student@master ansible]$ ansible node1 -m copy -a \'src=/etc/fstab dest=/var/tmp/fstab owner=zhang3 group=zhang3\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/var/tmp/fstab\", \"gid\": 1002, \"group\": \"zhang3\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"mode\": \"0644\", \"owner\": \"zhang3\", \"secontext\": \"unconfined_u:object_r:user_home_t:s0\", \"size\": 579, \"src\": \"/home/student/.ansible/tmp/ansible-tmp-1756266706.9290698-1517-277259149331136/source\", \"state\": \"file\", \"uid\": 1001}查看权限[student@master ansible]$ ansible node1 -m shell -a \'ls -l /var/tmp/fstab\'node1 | CHANGED | rc=0 >>-rw-r--r--. 1 zhang3 zhang3 579 Aug 27 11:51 /var/tmp/fstab
(四)文件属性模块:file
设置文件/目录的权限、所有者、类型(如创建文件、目录、链接)。
path
/dest
path=/var/tmp/fstab
)state
file
(确保为文件,默认) - directory
(创建目录) - link
(创建软链接) - hard
(创建硬链接) - touch
(创建空文件) - absent
(删除文件 / 目录)mode
mode=g+w
给组加写权限,或 mode=0644
)owner
owner=root
)group
group=root
)src
src=/aaa/file1 state=link
)修改node1的 /var/tmp/fstab
的权限(组可写、其他可写),所有者、所属组为root
:
[student@master ansible]$ ansible node1 -m file -a \'path=/var/tmp/fstab mode=g+w mode=o+w owner=root group=root \'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"gid\": 0, \"group\": \"root\", \"mode\": \"0646\", \"owner\": \"root\", \"path\": \"/var/tmp/fstab\", \"secontext\": \"unconfined_u:object_r:user_home_t:s0\", \"size\": 579, \"state\": \"file\", \"uid\": 0}
在远程创建目录 /aaa
,指定所有者为zhang3,所属组为root
[student@master ansible]$ ansible node1 -m file -a \'path=/aaa owner=zhang3 group=root state=directory\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"gid\": 0, \"group\": \"root\", \"mode\": \"0755\", \"owner\": \"zhang3\", \"path\": \"/aaa\", \"secontext\": \"unconfined_u:object_r:default_t:s0\", \"size\": 6, \"state\": \"directory\", \"uid\": 1001}
在远程创建空文件 /aaa/file1
,权限为0644:
[student@master ansible]$ ansible node1 -m file -a \'path=/aaa/file1 mode=0644 state=touch\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"dest\": \"/aaa/file1\", \"gid\": 0, \"group\": \"root\", \"mode\": \"0644\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:default_t:s0\", \"size\": 0, \"state\": \"file\", \"uid\": 0}
创建软链接:/aaa/abc
指向 /aaa/file1
:
[student@master ansible]$ ansible node1 -m file -a \'dest=/aaa/abc src=/aaa/file1 state=link\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"dest\": \"/aaa/abc\", \"gid\": 0, \"group\": \"root\", \"mode\": \"0777\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:default_t:s0\", \"size\": 10, \"src\": \"/aaa/file1\", \"state\": \"link\", \"uid\": 0}创建硬链接同上,仅需将state=link改为state=hard
删除远程 /aaa/file1
(文件/目录均适用):
[student@master ansible]$ ansible node1 -m file -a \'path=/aaa/file1 state=absent\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"path\": \"/aaa/file1\", \"state\": \"absent\"}
(五)YUM 仓库配置模块:yum_repository
在远程主机配置 YUM 仓库(生成 .repo
文件)。
file
.repo
文件名(如 file=server
对应 /etc/yum.repos.d/server.repo
)name
.repo
文件中 [NAME]
部分,如 name=BASE
)description
description=\"software base\"
)baseurl
baseurl=http://ansible.example.com/rhel9/BaseOS
)enabled
yes
(默认)、no
gpgcheck
yes
(默认)、no
gpgkey
gpgkey=http://xxx/RPM-GPG-KEY-redhat-release
)为所有主机配置 BASE
仓库(指向远程源):
[student@master ansible]$ ansible all -m yum_repository -a \'file=server name=BASE description=\"software base\" baseurl=http://ansible.example.com/rhel9/BaseOS enabled=yes gpgcheck=yes gpgkey=http://ansible.example.com/rhel9/RPM-GPG-KEY-redhat-release\'node2 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"BASE\", \"state\": \"present\"}node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"BASE\", \"state\": \"present\"}node3 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"BASE\", \"state\": \"present\"}node5 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"BASE\", \"state\": \"present\"}node4 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"BASE\", \"state\": \"present\"}
为所有主机配置 STREAM
仓库;
[student@master ansible]$ ansible all -m yum_repository -a \'file=server name=STREAM description=\"software stream\" baseurl=http://ansible.example.com/rhel9/AppStream enabled=yes gpgcheck=yes gpgkey=http://ansible.example.com/rhel9/RPM-GPG-KEY-redhat-release\'node2 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"STREAM\", \"state\": \"present\"}node3 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"STREAM\", \"state\": \"present\"}node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"STREAM\", \"state\": \"present\"}node4 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"repo\": \"STREAM\", \"state\": \"present\"}
(六)软件安装模块:yum
通过 YUM 管理器安装/卸载软件包(适用于 RHEL/CentOS 系统)。
name
name=httpd
,多个包如 name=httpd,nginx
)state
installed
/present
(安装软件,默认) - removed
/absent
(卸载软件) - latest
(升级到最新版本)update_cache
yes
、no
(默认)disable_gpg_check
yes
、no
(默认)所有主机安装 httpd
:
[student@master ansible]$ ansible all -m yum -a \'name=httpd state=installed\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"\", \"rc\": 0, \"results\": [ \"Installed: httpd-filesystem-2.4.53-7.el9.noarch\", \"Installed: mod_http2-1.15.19-2.el9.x86_64\", \"Installed: httpd-tools-2.4.53-7.el9.x86_64\", \"Installed: apr-util-openssl-1.6.1-20.el9.x86_64\", \"Installed: mod_lua-2.4.53-7.el9.x86_64\", \"Installed: httpd-2.4.53-7.el9.x86_64\", \"Installed: redhat-logos-httpd-90.4-1.el9.noarch\", \"Installed: mailcap-2.1.49-5.el9.noarch\", \"Installed: apr-1.7.0-11.el9.x86_64\", \"Installed: apr-util-1.6.1-20.el9.x86_64\", \"Installed: apr-util-bdb-1.6.1-20.el9.x86_64\", \"Installed: httpd-core-2.4.53-7.el9.x86_64\" ]}node4 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"\", \"rc\": 0, \"results\": [ \"Installed: httpd-filesystem-2.4.53-7.el9.noarch\", \"Installed: mod_http2-1.15.19-2.el9.x86_64\", \"Installed: httpd-tools-2.4.53-7.el9.x86_64\", \"Installed: apr-util-openssl-1.6.1-20.el9.x86_64\", \"Installed: mod_lua-2.4.53-7.el9.x86_64\", \"Installed: httpd-2.4.53-7.el9.x86_64\", \"Installed: redhat-logos-httpd-90.4-1.el9.noarch\", \"Installed: mailcap-2.1.49-5.el9.noarch\", \"Installed: apr-1.7.0-11.el9.x86_64\", \"Installed: apr-util-1.6.1-20.el9.x86_64\", \"Installed: apr-util-bdb-1.6.1-20.el9.x86_64\", \"Installed: httpd-core-2.4.53-7.el9.x86_64\" ]}node2 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"\", \"rc\": 0, \"results\": [ \"Installed: httpd-filesystem-2.4.53-7.el9.noarch\", \"Installed: mod_http2-1.15.19-2.el9.x86_64\", \"Installed: httpd-tools-2.4.53-7.el9.x86_64\", \"Installed: apr-util-openssl-1.6.1-20.el9.x86_64\", \"Installed: mod_lua-2.4.53-7.el9.x86_64\", \"Installed: httpd-2.4.53-7.el9.x86_64\", \"Installed: redhat-logos-httpd-90.4-1.el9.noarch\", \"Installed: mailcap-2.1.49-5.el9.noarch\", \"Installed: apr-1.7.0-11.el9.x86_64\", \"Installed: apr-util-1.6.1-20.el9.x86_64\", \"Installed: apr-util-bdb-1.6.1-20.el9.x86_64\", \"Installed: httpd-core-2.4.53-7.el9.x86_64\" ]}node3 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"\", \"rc\": 0, \"results\": [ \"Installed: httpd-filesystem-2.4.53-7.el9.noarch\", \"Installed: mod_http2-1.15.19-2.el9.x86_64\", \"Installed: httpd-tools-2.4.53-7.el9.x86_64\", \"Installed: apr-util-openssl-1.6.1-20.el9.x86_64\", \"Installed: mod_lua-2.4.53-7.el9.x86_64\", \"Installed: httpd-2.4.53-7.el9.x86_64\", \"Installed: redhat-logos-httpd-90.4-1.el9.noarch\", \"Installed: mailcap-2.1.49-5.el9.noarch\", \"Installed: apr-1.7.0-11.el9.x86_64\", \"Installed: apr-util-1.6.1-20.el9.x86_64\", \"Installed: apr-util-bdb-1.6.1-20.el9.x86_64\", \"Installed: httpd-core-2.4.53-7.el9.x86_64\" ]}node5 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"\", \"rc\": 0, \"results\": [ \"Installed: httpd-filesystem-2.4.53-7.el9.noarch\", \"Installed: mod_http2-1.15.19-2.el9.x86_64\", \"Installed: httpd-tools-2.4.53-7.el9.x86_64\", \"Installed: apr-util-openssl-1.6.1-20.el9.x86_64\", \"Installed: mod_lua-2.4.53-7.el9.x86_64\", \"Installed: httpd-2.4.53-7.el9.x86_64\", \"Installed: redhat-logos-httpd-90.4-1.el9.noarch\", \"Installed: mailcap-2.1.49-5.el9.noarch\", \"Installed: apr-1.7.0-11.el9.x86_64\", \"Installed: apr-util-1.6.1-20.el9.x86_64\", \"Installed: apr-util-bdb-1.6.1-20.el9.x86_64\", \"Installed: httpd-core-2.4.53-7.el9.x86_64\" ]}
[student@master ansible]$ ansible node4 -m yum -a \'name=httpd state=removed\'node4 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"\", \"rc\": 0, \"results\": [ \"Removed: httpd-2.4.53-7.el9.x86_64\" ]}
卸载 软件httpd
:
state=absent也能够卸载软件[student@master ansible]$ ansible node4 -m yum -a \'name=httpd state=removed\'node4 | 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
name=httpd
,需与系统服务名一致)state
started
(启动服务) - stopped
(停止服务) - restarted
(重启服务) - reloaded
(重载配置)enabled
yes
(启用)、no
(禁用)、masked
(屏蔽服务)daemon_reload
daemon_reload=yes
)设置node1启动 httpd
服务,并设置开机自启:
[student@master ansible]$ ansible node1 -m service -a \'name=httpd state=started enabled=yes\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"enabled\": true, \"name\": \"httpd\", \"state\": \"started\", \"status\": { \"AccessSELinuxContext\": \"system_u:object_r:httpd_unit_file_t:s0\", \"ActiveEnterTimestampMonotonic\": \"0\", \"ActiveExitTimestampMonotonic\": \"0\", ********省略********* \"UnitFileState\": \"disabled\", \"UtmpMode\": \"init\", \"Wants\": \"httpd-init.service\", \"WatchdogSignal\": \"6\", \"WatchdogTimestampMonotonic\": \"0\", \"WatchdogUSec\": \"infinity\" }}
重启 httpd
服务;
[student@master ansible]$ ansible node1 -m service -a \'name=httpd state=restarted\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"name\": \"httpd\", \"state\": \"started\", \"status\": { \"AccessSELinuxContext\": \"system_u:object_r:httpd_unit_file_t:s0\", \"ActiveEnterTimestamp\": \"Wed 2025-08-27 12:31:39 CST\", \"ActiveEnterTimestampMonotonic\": \"6241006629\", \"ActiveExitTimestampMonotonic\": \"0\", *******省略******* \"WatchdogSignal\": \"6\", \"WatchdogTimestampMonotonic\": \"0\", \"WatchdogUSec\": \"0\" }}
(八)文件拉取模块:fetch
从远程主机拉取文件到本地(仅支持文件,不支持目录;本地存储以主机名分目录)。
src
src=/etc/fstab
,必须是文件,不能是目录)dest
dest=/tmp/
,拉取后默认生成 dest/主机名/src路径
结构)flat
yes
(直接存为 dest/文件名
,如 dest=/tmp/fstab
)、no
(默认)validate_checksum
yes
(默认)、no
拉取所有远程主机的 /etc/fstab
到本地 /tmp
(本地路径:/tmp//etc/fstab
):
[student@master ansible]$ ansible all -m fetch -a \'src=/etc/fstab dest=/tmp/\'node4 | CHANGED => { \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/tmp/node4/etc/fstab\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"remote_checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"remote_md5sum\": null}node1 | CHANGED => { \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/tmp/node1/etc/fstab\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"remote_checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"remote_md5sum\": null}node3 | CHANGED => { \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/tmp/node3/etc/fstab\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"remote_checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"remote_md5sum\": null}node2 | CHANGED => { \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/tmp/node2/etc/fstab\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"remote_checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"remote_md5sum\": null}node5 | CHANGED => { \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/tmp/node5/etc/fstab\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"remote_checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"remote_md5sum\": null}[student@master ansible]$ ls /tmp/node1node2node3node4node5[student@master etc]$ lsfstab[student@master etc]$ pwd/tmp/node1/etc
拉取 node1
的 /etc/fstab
到本地 /tmp/fstab
(不创建主机名目录):
[student@master ansible]$ ansible node1 -m fetch -a \'src=/etc/fstab dest=/tmp/ flat=yes\'node1 | CHANGED => { \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/tmp/fstab\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"remote_checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"remote_md5sum\": null}[student@master ansible]$ ls /tmp/fstabnode1node2node3node4node5
拉取所有node2的 /etc/fstab
到本地,文件名含主机名(如 /tmp/fstab-node1
):
[student@master ansible]$ ansible node2 -m fetch -a \'src=/etc/fstab dest=/tmp/fstab-{{inventory_hostname}} flat=yes\'node2 | CHANGED => { \"changed\": true, \"checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"dest\": \"/tmp/fstab-node2\", \"md5sum\": \"4ab05d98a2058dd0703b9e57993802e8\", \"remote_checksum\": \"741593a3c559105fd9a9af53e25a3684ce00a57e\", \"remote_md5sum\": null}[student@master ansible]$ ls /tmp/fstabfstab-node2node1node2node3node4node5
(九)防火墙配置模块:firewalld
管理 firewalld 防火墙规则(端口、服务、富规则)。
service
service=http
,需 firewalld 预定义服务)port
port=80/tcp
,格式 端口/协议
)rich_rule
rich_rule=\"rule family=ipv4 source address=192.168.122.0/24 service name=http accept\"
)zone
zone=public
,默认 public)state
enabled
(启用规则)、disabled
(禁用规则)permanent
yes
(重启 firewalld 后保留)、no
(临时生效,默认)immediate
permanent=yes
使用,immediate=yes
实现 “永久 + 即时生效”)所有主机允许 http
服务流量(永久生效,立即加载):
[student@master ansible]$ ansible all -m firewalld -a \'service=http permanent=yes state=enabled immediate=yes\'node5 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed service http to enabled\"}node3 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed service http to enabled\"}node4 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed service http to enabled\"}node2 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed service http to enabled\"}node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed service http to enabled\"}
允许 192.168.122.0/24
网段访问 http
服务(永久生效):
[student@master ansible]$ ansible all -m firewalld -a \'zone=public rich_rule=\"rule family=ipv4 source address=192.168.122.0/24 service name=http accept\" permanent=yes state=enabled immediate=yes\'node2 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed rich_rule rule family=ipv4 source address=192.168.122.0/24 service name=http accept to enabled\"}node3 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed rich_rule rule family=ipv4 source address=192.168.122.0/24 service name=http accept to enabled\"}node4 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed rich_rule rule family=ipv4 source address=192.168.122.0/24 service name=http accept to enabled\"}node5 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed rich_rule rule family=ipv4 source address=192.168.122.0/24 service name=http accept to enabled\"}node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"Permanent and Non-Permanent(immediate) operation, Changed rich_rule rule family=ipv4 source address=192.168.122.0/24 service name=http accept to enabled\"}
(十)文件内容替换模块:replace
path
path=/aaa/file11
)regexp
regexp=\"aa\"
匹配所有 “aa”)replace
replace=\"zz\"
将 “aa” 替换为 “zz”)backup
yes
(备份为 path.xxx~
)、no
(默认)before
before=\"abc\"
替换 abc 之前的匹配项)after
after=\"abc\"
替换 abc 之后的匹配项)通过正则表达式替换文件中的字符串(支持备份)。
创建一个文件:
[student@master ansible]$ ansible node1 -m shell -a \'echo aa bb abc aa asd qwe aa > /aaa/file11\'node1 | CHANGED | rc=0 >>[student@master ansible]$ ansible node1 -m shell -a \'cat /aaa/file11\'node1 | CHANGED | rc=0 >>aa bb abc aa asd qwe aa
将node1中 /aaa/file11
中的 aa
替换为 zz
:
[student@master ansible]$ ansible node1 -m replace -a \'path=/aaa/file11 regexp=\"aa\" replace=\"zz\"\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"3 replacements made\", \"rc\": 0}[student@master ansible]$ ansible node1 -m shell -a \'cat /aaa/file11\'node1 | CHANGED | rc=0 >>zz bb abc zz asd qwe zz
替换字符串并备份原文件(备份文件后缀为 .bak
):
[student@master ansible]$ ansible node1 -m replace -a \'path=/aaa/file11 regexp=\"zz\" replace=\"kk\" backup=yes\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"backup_file\": \"/aaa/file11.16916.2025-08-27@12:58:34~\", \"changed\": true, \"msg\": \"3 replacements made\", \"rc\": 0}[student@master ansible]$ ansible node1 -m shell -a \'cat /aaa/file11\'node1 | CHANGED | rc=0 >>kk bb abc kk asd qwe kk[student@master ansible]$ ansible node1 -m shell -a \'ls /aaa/\'node1 | CHANGED | rc=0 >>file11file11.16916.2025-08-27@12:58:34~[student@master ansible]$ ansible node1 -m shell -a \'cat /aaa/file11.16916.2025-08-27@12:58:34~\'node1 | CHANGED | rc=0 >>zz bb abc zz asd qwe zz
(十一)磁盘分区模块:parted
管理磁盘分区(新建、删除分区)。
device
device=/dev/vdb
)number
number=1
表示第一个分区)state
present
(创建分区)、absent
(删除分区)part_type
primary
(主分区)、extended
(扩展分区)、logical
(逻辑分区)part_start
part_end
在 node5
的 /dev/vdb
上新建扩展分区(编号 1,起始 1GiB,结束 20GiB):
[student@master ansible]$ ansible node5 -m parted -a \'device=/dev/vdb number=1 part_type=extended part_start=1GiB part_end=20GiB state=present\'node5 | 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\": 52428800.0, \"table\": \"msdos\", \"unit\": \"kib\" }, \"partitions\": [ { \"begin\": 1048576.0, \"end\": 20971520.0, \"flags\": [ \"lba\" ], \"fstype\": \"\", \"name\": \"\", \"num\": 1, \"size\": 19922944.0, \"unit\": \"kib\" } ], \"script\": \"unit KiB mklabel msdos mkpart extended 1GiB 20GiB\"}[student@master ansible]$ ansible node5 -m shell -a \'lsblk /dev/vdb\'node5 | CHANGED | rc=0 >>NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTSvdb 252:16 0 50G 0 disk └─vdb1 252:17 0 1K 0 part
在扩展分区内新建逻辑分区(编号 ,起始 1.1GiB,结束 10GiB):
[student@master ansible]$ ansible node5 -m parted -a \'device=/dev/vdb number=5 part_type=logical part_start=1.1GiB part_end=10GiB state=present\'node5 | 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\": 52428800.0, \"table\": \"msdos\", \"unit\": \"kib\" }, \"partitions\": [ { \"begin\": 1048576.0, \"end\": 20971520.0, \"flags\": [ \"lba\" ], \"fstype\": \"\", \"name\": \"\", \"num\": 1, \"size\": 19922944.0, \"unit\": \"kib\" }, { \"begin\": 1153434.0, \"end\": 10485760.0, \"flags\": [], \"fstype\": \"\", \"name\": \"\", \"num\": 5, \"size\": 9332327.0, \"unit\": \"kib\" } ], \"script\": \"unit KiB mkpart logical 1.1GiB 10GiB\"}
(十二)文件系统模块:filesystem
为分区创建文件系统如 XFS、EXT4(格式化为XFS.EXT4类型)。
dev
dev=/dev/vdb5
)fstype
fstype=xfs
、fstype=ext4
)force
force=yes
,谨慎使用)opts
opts=\"-m 5\"
给 EXT4 预留 5% 空间)为 node5
的 /dev/sda5
分区创建 XFS 文件系统:
[student@master ansible]$ ansible node5 -m filesystem -a \'fstype=xfs dev=/dev/vdb5\'node5 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true}
(十三)挂载模块:mount
管理文件系统挂载(临时挂载、写入 /etc/fstab
永久挂载)。
path
/name
path=/fs
,需先创建目录)src
src=/dev/vdb5
,或 UUID 如 src=\"UUID=xxx\"
)fstype
fstype=xfs
,需与分区格式一致)state
mounted
(挂载并写入 /etc/fstab
永久生效) - present
(仅写入 /etc/fstab
,不立即挂载) - unmounted
(卸载,保留 /etc/fstab
) - absent
(卸载并删除 /etc/fstab
配置)opts
opts=defaults
,默认 defaults
)在 node1
上创建挂载点 /fs
略
查看 /dev/vda5
的 UUID:
[student@master ansible]$ ansible node5 -m shell -a \'blkid /dev/vdb5\'node5 | CHANGED | rc=0 >>/dev/vdb5: UUID=\"7facb414-b6a8-403d-9b28-22f3ebb5c9e5\" TYPE=\"xfs\" PARTUUID=\"ebc69adf-05\"
将 /dev/vda5
永久挂载到 /fs
(写入 /etc/fstab
):
[student@master ansible]$ ansible node5 -m mount -a \'path=/fs src=\"UUID=7facb414-b6a8-403d-9b28-22f3ebb5c9e5\" fstype=xfs state=absent\'node5 | SUCCESS => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"backup_file\": \"\", \"boot\": \"yes\", \"changed\": false, \"dump\": \"0\", \"fstab\": \"/etc/fstab\", \"fstype\": \"xfs\", \"name\": \"/fs\", \"opts\": \"defaults\", \"passno\": \"0\", \"src\": \"UUID=7facb414-b6a8-403d-9b28-22f3ebb5c9e5\"}
(十四)LVM 卷组模块:lvg
创建、删除 LVM 卷组。
vg
vg=vg0
)pvs
pvs=/dev/vdb5
,多个物理卷用逗号分隔)state
present
(创建卷组)、absent
(删除卷组)pesize
pesize=16M
,默认 4M,需是 2 的幂)force
force=yes
,谨慎使用)在 node5
上创建卷组 vg0
,使用 /dev/vda5
分区,PE 大小 16M:
[student@master ansible]$ ansible node5 -m lvg -a \'vg=vg0 pesize=16M pvs=/dev/vdb5\'node5 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true}
(十五)LVM 逻辑卷模块:lvol
创建、扩容 LVM 逻辑卷。
lv
lv=lv0
)vg
vg=vg0
)size
size=1000M
、size=+500M
表示扩容 500M)state
present
(创建 / 保留)、absent
(删除)resizefs
yes
(需文件系统支持,如 XFS/EXT4)、no
(默认)在卷组 vg0
上创建 1000M 的逻辑卷 lv0
:
[student@master ansible]$ ansible node5 -m lvol -a \'lv=lv0 size=1000M vg=vg0\'node5 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"msg\": \"\"}
在线扩容 lv0
到 1600M(自动扩展文件系统);
# 为逻辑卷 lv0 格式化为 XFS 文件系统(加 -b 提权)[student@master ansible]$ ansible node5 -m filesystem -a \'fstype=xfs dev=/dev/vg0/lv0\'node5 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true}# 扩容到 1600M[student@master ansible]$ ansible node5 -m lvol -a \'lv=lv0 size=1600M vg=vg0 resizefs=yes\'node5 | SUCCESS => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": false, \"lv\": \"lv0\", \"size\": 1600.0, \"vg\": \"vg0\"}
(十六)计划任务模块:cron
管理远程主机的 crontab 计划任务。
name
name=\"shuchu\"
)job
job=\"/bin/echo I AM RHCE\"
)user
user=root
,默认当前用户)state
present
(创建任务)、absent
(删除任务)minute
/hour
/day
/month
/weekday
minute=0
(分钟,0-59) - hour=14
(小时,0-23) - day=*
(日,1-31) - month=*
(月,1-12) - weekday=*
(周,0-6,0 = 周日)special_time
reboot
(重启时)、daily
(每天)等在 node1
上添加计划任务:每天 14:00 以 root
执行 /bin/echo I AM RHCE
:
[student@master ansible]$ ansible node1 -m cron -a \'name=\"shuchu\" job=\"/bin/echo I AM RHCE\" user=root minute=0 hour=14 state=present\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"envs\": [], \"jobs\": [ \"shuchu\" ]}
删除上述计划任务;
[student@master ansible]$ ansible node1 -m cron -a \'name=\"shuchu\" state=absentnode1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"envs\": [], \"jobs\": []}
(十七)文件下载模块:get_url
从 HTTP/HTTPS/FTP 下载文件到远程主机。
url
url=http://ansible.example.com/file2
)dest
dest=/tmp/file2
)owner
/group
/mode
copy
模块,设置下载后文件的所有者、所属组、权限force
yes
、no
(默认,校验 MD5 一致则不下载)validate_certs
yes
(默认)、no
(忽略证书错误)timeout
timeout=30
,单位秒,默认 10 秒)在 node1
上下载文件(如远程 http://ansilbe.example.com/file2
到 /tmp/
):
[student@master ansible]$ ansible node1 -m get_url -a \'url=http://ansible.example.com/file2 dest=/tmp/file2\'node1 | CHANGED => { \"ansible_facts\": { \"discovered_interpreter_python\": \"/usr/bin/python3\" }, \"changed\": true, \"checksum_dest\": null, \"checksum_src\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"dest\": \"/tmp/file2\", \"elapsed\": 0, \"gid\": 0, \"group\": \"root\", \"md5sum\": \"d41d8cd98f00b204e9800998ecf8427e\", \"mode\": \"0644\", \"msg\": \"OK (0 bytes)\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:user_home_t:s0\", \"size\": 0, \"src\": \"/home/student/.ansible/tmp/ansible-tmp-1756305253.1840584-1389-107803694225127/tmpyo819el6\", \"state\": \"file\", \"status_code\": 200, \"uid\": 0, \"url\": \"http://ansible.example.com/file2\"}
node1
上下载文件(如远程 http://example.com/file.tar.gz
到 /tmp/
)ansible node1 -m get_url -a \'url=http://example.com/file.tar.gz dest=/tmp/file.tar.gz\'
ansible node1 -m get_url -a \'url=http://example.com/file.tar.gz dest=/tmp/file.tar.gz force=yes\'