跳转至

Ansible模块3

一. lineinfile模块

1. 简介

ansible在使用sed进行替换的时候,经常会遇到需要转义的问题。这时候ansible在遇到特殊符号进行替换存在问题可能无法正常进行替换。这时候我们就需要ansible自身提供的两个模块 --- lineinfile模块和replace模块

一般来说,ansible当中修改某个文件的单行进行替换时使用lineinfile模块

2. 核心参数

path: 必填,要操作文件的路径

regexp: 使用正则表达式匹配对应的行。

  • 当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才能被替换

  • 当删除文本时,如果有多行文本都能被匹配,则所有能被匹配到的行都会被替换

如果项进行多行匹配替换需要使用replace模块

line: 要写入的新行内容(替换匹配行,没匹配到就按位置插入)

state: 状态

  • present: 默认选项,确保行在

  • absent: 删除所有匹配regexp的行

insertafter/insertbefore: 没匹配到时,插到哪里(insertafter=EOF(默认)/EOF/匹配行)

create: 文件不存在时是否创建,默认为no

3. 命令格式

lineinfile模块在ansible使用时,标准的写法是

ansible <目标主机> -m lineinfile -a '属性1=值1' '属性2=值2' ... 属性n=值n

4. 实践

1) 将指定文件匹配到的内容进行行替换

a. 准备文件

[root@1 ~]# ansible -m copy -a "content='server {\n listen 8080;\n}' dest=/tmp/nginx_test.conf" web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "checksum": "3968e4d34e4490b9a1517ceca3537a1aaff23f66",
    "dest": "/tmp/nginx_test.conf",
    "gid": 0,
    "group": "root",
    "md5sum": "e03834d61c749f1ca8da4a1217bc6383",
    "mode": "0644",
    "owner": "root",
    "secontext": "unconfined_u:object_r:admin_home_t:s0",
    "size": 24,
    "src": "/root/.ansible/tmp/ansible-tmp-1786879818.2770197-1623-184718525988738/source",
    "state": "file",
    "uid": 0
}
# 查看文件内容
[root@1 ~]# ansible -m shell -a "cat /tmp/nginx_test.conf" web_servers1
2 | CHANGED | rc=0 >>
server {
 listen 8080;
}

b. 将指定文件进行"行替换"

[root@1 ~]# ansible -m lineinfile -a "path=/tmp/nginx_test.conf regexp='listen' line=' listen80'" web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "backup": "",
    "changed": true,
    "msg": "line replaced"
}
# 查看效果
[root@1 ~]# ansible -m shell -a "cat /tmp/nginx_test.conf" web_servers1
2 | CHANGED | rc=0 >>
server {
 listen80
}

2) 将指定文件匹配到内容进行删除

[root@1 ~]# ansible -m lineinfile -a "path=/tmp/nginx_test.conf regexp='listen80' state=absent" web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "backup": "",
    "changed": true,
    "found": 1,
    "msg": "1 line(s) removed"
}

查看验证

[root@1 ~]# ansible -m shell -a "cat /tmp/nginx_test.conf" web_servers1
2 | CHANGED | rc=0 >>
server {
}

二. replace模块

1. 简介

replace模块相较于lineinfile模块来说,更倾向于sed命令的操作,尤其是多行匹配进行替换

2. 命令格式

replace模块在ansible使用时,标准的写法是

ansible <目标主机> -m replace -a '属性1=值1 属性2=值2 ... 属性n=值n'

3. 常见参数

path: 文件路径

regexp: 匹配要替换的字符串本身,不会进行整行替换

replace: 指定替换后的字符

after/before: 只在指定锚点之后/之前进行替换

backup/validate: 备份/校验

4. 准备测试文件

准备测试文件

[root@1 ~]# ansible -m shell -a "grep default /etc/fstab >> /tmp/fstab ; cat /tmp/fstab" web_servers1
2 | CHANGED | rc=0 >>
/dev/mapper/rl-root     /                       xfs     defaults        0 0
UUID=0530d8e4-6a96-4c29-a3cd-66607d24bd3a /boot                   xfs     defaults        0 0
/dev/mapper/rl-home     /home                   xfs     defaults        0 0
/dev/mapper/rl-swap     none                    swap    defaults        0 0

将文件内容进行多行匹配替换

[root@1 ~]# ansible -m replace -a "path=/tmp/fstab regexp='(defau.*)' replace='#\1'" web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "msg": "4 replacements made",
    "rc": 0
}

查看效果

[root@1 ~]# ansible -m shell -a "cat /tmp/fstab" web_servers1
2 | CHANGED | rc=0 >>
/dev/mapper/rl-root     /                       xfs     #defaults        0 0
UUID=0530d8e4-6a96-4c29-a3cd-66607d24bd3a /boot                   xfs     #defaults        0 0
/dev/mapper/rl-home     /home                   xfs     #defaults        0 0
/dev/mapper/rl-swap     none                    swap    #defaults        0 0

再替换回去

[root@1 ~]# ansible -m replace -a "path=/tmp/fstab regexp='#(defau.*)' replace='\1'" web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "msg": "4 replacements made",
    "rc": 0
}
# 查看效果
[root@1 ~]# ansible -m shell -a "cat /tmp/fstab" web_servers1
2 | CHANGED | rc=0 >>
/dev/mapper/rl-root     /                       xfs     defaults        0 0
UUID=0530d8e4-6a96-4c29-a3cd-66607d24bd3a /boot                   xfs     defaults        0 0
/dev/mapper/rl-home     /home                   xfs     defaults        0 0
/dev/mapper/rl-swap     none                    swap    defaults        0 0

三. yum_repository模块

1. 简介

此模块用来对远程主机上的rpm包仓库进行管理。(注:也存在dnf_repository模块,但是需要额外按照)

2. 常见参数

name: 必填,仓库ID

description: 仓库描述

baseurl: 仓库地址(mirrorlist二选一)

mirrorlist: 镜像列表

file: 写入的.repo文件名(默认用name,不需要带.repo后缀)

enabled: 是否启用。yes|no

gpgcheck: 是否校验GPG。yes|no

gpgkey: 公钥URL

state: present(创建/更新)/absent(删除)

3. 实践

1) 添加镜像仓库

[root@1 ~]# ansible -m yum_repository -a "name=epel description='aliyunEPEL' baseurl='https://mirrors.aliyun.com/epel/\$releasever/Everything/\$basearch/' file=aliyunepel enabled=yes gpgcheck=no state=present" web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "repo": "epel",
    "state": "present"
}

检查效果

[root@1 ~]# ansible -m shell -a "ls -l /etc/yum.repos.d/aliyunepel.repo;cat /etc/yum.repos.d/aliyunepel.repo" web_servers1
2 | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 127  8月 17 10:00 /etc/yum.repos.d/aliyunepel.repo
[epel]
baseurl = https://mirrors.aliyun.com/epel/$releasever/Everything/$basearch/
enabled = 1
gpgcheck = 0
name = aliyunEPEL

2) 更新软件源

[root@1 ~]# ansible -m shell -a "dnf makecache" web_servers1
2 | CHANGED | rc=0 >>
aliyunEPEL                                      405 kB/s |  21 MB     00:52    
Rocky Linux 9 - BaseOS                          1.1 kB/s | 4.3 kB     00:04    
Rocky Linux 9 - BaseOS                          152 kB/s |  21 MB     02:21    
Rocky Linux 9 - AppStream                       1.9 kB/s | 4.8 kB     00:02    
Rocky Linux 9 - AppStream                       361 kB/s |  19 MB     00:55    
Rocky Linux 9 - Extras                          676  B/s | 3.1 kB     00:04    
Rocky Linux 9 - Extras                          7.5 kB/s |  17 kB     00:02    
元数据缓存已建立。Repository epel is listed more than once in the configuration

3) 删除镜像仓库

[root@1 ~]# ansible -m yum_repository -a 'file=aliyunepel name=epel state=absent' web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "repo": "epel",
    "state": "absent"
}

查看验证

[root@1 ~]# ansible -a "ls /etc/yum.repos.d/" web_servers1
2 | CHANGED | rc=0 >>
rocky-addons.repo
rocky-devel.repo
rocky-extras.repo
rocky.repo

此时我们会发现aliyunepel.repo没了

四. service模块

1. 简介

service模块主要适用于远程客户端各种服务管理,包括启动、停止、重启、重载等

2. 详细参数

name参数: 此参数用于指定需要操作的服务名称。比如nginx,httpd

state参数: 此参数用于指定服务的状态。比如我们想要启动远程主机的httpd,就可以将state的值设置为started;如果想要停止远程主机中的服务,则可以将state的值设置为stopped。

  • started: 启动服务

  • stopped: 停止服务

  • restarted: 重启服务

  • reloaded: 重新加载服务

enabled参数: 此参数用于指定是否将服务设置为开机自启动。设置为yes表示将对应的服务设置为开机自启动,设置为no表示不会开机启动

runlevel参数: 服务启动级别

arguments参数: 服务命令行参数传递

注: 想使用service模块启动服务,被启动的服务必须可以使用service命令启动或者关闭

3. 命令格式

service模块在ansible使用时,标准的写法是

ansible <目标主机> -m servoce -a '属性1=值1 属性2=值2 ... 属性n=值n'

4. 实践

1) 查看已安装的软件

[root@1 ~]# ansible -m dnf -a "name=httpd state=present" web_servers1
2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "msg": "Nothing to do",
    "rc": 0,
    "results": []
}

2) 设置开机自启动

[root@1 ~]# ansible -m service -a "name=httpd enabled=yes" web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "enabled": true,
    "name": "httpd",
...

检查效果

[root@1 ~]# ansible -a "systemctl is-enabled httpd" -o web_servers1
2 | CHANGED | rc=0 | (stdout) enabled

关闭开机自启动

[root@1 ~]# ansible -m service -a "name=httpd enabled=false" web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "enabled": false,
    "name": "httpd",
...

查看效果

[root@1 ~]# ansible -a "systemctl is-enabled httpd" web_servers1
2 | FAILED | rc=1 >>
disablednon-zero return code

3) 启动服务

[root@1 ~]# ansible -m service -a 'name=httpd state=started' web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "name": "httpd",
    "state": "started",
...

检查效果

[root@1 ~]# ansible -m shell -a 'ss -tuanp|grep httpd' web_servers1
2 | CHANGED | rc=0 >>
tcp   LISTEN 0      511                  *:80                *:*     users:(("httpd",pid=12651,fd=4),("httpd",pid=12650,fd=4),("httpd",pid=12649,fd=4),("httpd",pid=12647,fd=4))

4) 重启服务

[root@1 ~]# ansible -m service -a 'name=httpd state=restarted' web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "name": "httpd",
    "state": "started",
...

5) 关闭服务

[root@1 ~]# ansible -m service -a 'name=httpd state=stopped' web_servers1
2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "name": "httpd",
    "state": "stopped",
...

检查效果

[root@1 ~]# ansible -m shell -a 'ss -tuanp|grep httpd' web_servers1
2 | FAILED | rc=1 >>
non-zero return code

五. template模块

1. 简介

template模块用于把控制机上的Jinja2模板文件(.j2)渲染成目标主机的配置文件。适合"每台主机配置不一样"的场景(主机名、IP、端口等)。

它与copy模块的区别:

copy: 原样拷贝,所有主机内容一模一样

template: 按变量渲染,每台主机内容可以不同

注: Jinja2是Python的模板引擎库,不是ansible模块。ansible本身是Python写的,template模块内部就是调用Jinja2来渲染模板。所以我们只需要会写 {{ }} 模板语法即可,不需要会写Python代码。

2. 常见参数

src: 必填。控制机上的 .j2 模板文件路径

dest: 必填。目标机上的最终文件路径

owner/group: 渲染后文件的属主/属组

mode: 渲染后文件的权限

backup: 覆盖前是否备份。默认no

validate: 渲染后先校验再落盘(如nginx写"nginx -t")

force: 内容变化时是否强制覆盖。默认yes

3. Jinja2模板语法(三种括号)

{{ 变量 }}: 输出变量值

示例: {{ ansible_hostname }} → 输出该主机的主机名

{% 控制 %}: 逻辑控制(循环/判断)

{% for x in list %} ... {% endfor %} 循环

{% if 条件 %} ... {% else %} ... {% endif %} 判断

{# 注释 #}: 注释,不会输出

过滤器 |: 对值做处理

{{ name | upper }} 转大写

{{ my_var | default('默认值') }} 变量为空时给默认值

{{ item | upper }} 循环项转大写

模板中可以直接使用setup模块收集的facts变量

{{ ansible_hostname }}: 主机名

{{ ansible_default_ipv4.address }}: 默认网卡IP

{{ ansible_processor_cores }}: CPU核数

{{ ansible_memtotal_mb }}: 内存大小(MB)

{{ ansible_all_ipv4_addresses }}: 所有IPv4地址列表

4. 命令格式

template模块在ansible使用时,标准的写法是

ansible <目标主机> -m template -a 'src=模板路径 dest=目标路径 其他属性'

自定义变量用-e传递,如: ansible -m template -a "..." -e "http_port=8080"

5. 实践

1) 在控制机准备模板文件

[root@1 ~]# cat > /root/nginx_test.conf.j2 <<'EOF'
server {
    listen {{ http_port }};
    server_name {{ ansible_hostname }};
    allow {{ ansible_default_ipv4.address }};
}
EOF

2) 使用template分发到目标主机(用-e传自定义变量http_port)

[root@1 ~]# ansible -m template -a "src=/root/nginx_test.conf.j2 dest=/tmp/nginx_test.conf" -e "http_port=8080" web_servers*

3) 查看效果(每台主机的hostname和IP会不同)

[root@1 ~]# ansible -a "cat /tmp/nginx_test.conf" web_servers*
# 此处贴实际运行输出