十一、Ansible文件操作模块(三)
blockinfile模块
blockinfile模块可以帮助我们在指定的文件中插入”一段标记的文本”,我们可以通过”标记”找到这段文本,然后修改或者删除这段文本。
案例
一、实验前的准备
使用rc.local做为测试文件,将其复制到/testdir目录下
$ mkdir /testdir
$ cp /etc/rc.d/rc.local /testdir
二、相关案例
1、在db_servers主机中的/testdir/rc.local文件尾部插入如下两行文本
systemctl start mariadb
systemctl start httpd
$ ansible db_servers -m blockinfile -a \
'path=/testdir/rc.local block="systemctl start mariadb\nsystemctl start httpd" '
该案例中使用block参数指定文本块内容,当执行上述命令后,/testdir/rc.local的文件尾部会多出如下文本

正如之前所说,blockinfile模块的作用就是在文件中添加、更新、或者删除”被标记的文本块”,而上述被标记的文本块就是我们添加进文件的,# BEGIN ANSIBLE MANAGED BLOCK 和 # END ANSIBLE MANAGED BLOCK 就是blockinfile模块自动为我们添加的文本块标记,一个是开始标记,一个是结束标记。
2、自定义标记
注意自定义的标记要”成对出现”,需要有开始标记和结束标记,示例如下
$ ansible db_servers -m blockinfile -a \
'path=/testdir/rc.local \
block="systemctl start mariadb\nsystemctl start httpd" marker="#{mark} serivce to start" '
使用marker可以自定义文本块的标记, 上例中的”{mark}” 会自动被替换成开始标记中的”BEGIN” 和结束标记中的 “END”,如果文件中不存在同名标记的文本块,那么文件的末尾将会出现如下文本块

3、修改标记文本内容
在执行完案例2的基础上,执行如下命令
$ ansible db_servers -m blockinfile -a \
'path=/testdir/rc.local block="tz tz tz!!!" marker="#{mark} serivce to start" '
当标记相同,文本块内容不同时,文本块的内容会被更新。

4、删除标记文本内容
两种删除方式
$ ansible db_servers -m blockinfile -a \
'path=/testdir/rc.local block="" marker="#{mark} serivce to start" '
$ ansible db_servers -m blockinfile -a \
'path=/testdir/rc.local marker="#{mark} serivce to start" state=absent'
5、将标记文本插入到文件开头
使用insertbefore参数,将其值设置为BOF,BOF表示Begin Of File,可以将文本块插入到文档开头。
$ ansible db_servers -m blockinfile -a \
'path=/testdir/rc.local block="####blockinfile test####" marker="#{mark} test" insertbefore=BOF'
效果如下

使用insertafter参数,将其值设置为EOF,EOF表示End Of File,表示将文本插入到文档尾部,也可以不写该参数,因为默认就将文本插入到文档尾部。
6、使用正则表达式
使用正则表达式匹配行,将文本块插入到 “以#!/bin/bash开头的行” 之后
$ ansible db_servers -m blockinfile -a \
'path=/testdir/rc.local block="####blockinfile test####" marker="#{mark} test reg" insertafter="^#!/bin/bash" '
7、修改文件前备份文件
$ ansible db_servers -m blockinfile -a \
'path=/testdir/rc.local marker="#{mark} test" state=absent backup=yes'
备份的文件会在原文件名的基础上添加时间戳
8、如果指定的文件不存在,则创建它
$ ansible db_servers -m blockinfile -a \
'path=/testdir/test block="test" marker="#{mark} test" create=yes'
效果如下

常用参数
-
path
必须参数,指定要操作的文件。 -
block
此参数用于指定文本块,也可以使用别名”content”。 -
marker
指定开始标记跟结束标记,默认开始标记为# BEGIN ANSIBLE MANAGED BLOCK,结束标记为# END ANSIBLE MANAGED BLOCK,也可以使用marker参数自定义”标记”,比如,marker=#{mark}test ,这样设置以后,开始标记变成了# BEGIN test,结束标记变成了# END test。 -
state
state参数有两个可选值,present与absent,默认值为present,表示如果对应的文件中已经存在对应标记的文本,则会更新对应文本块;
如果state的值设置为absent,则表示从文件中删除对应标记的文本块。 -
insertafter 不指定该参数时默认会在文件的末尾插入文本,如果你想要将文本插入在某一行的后面,可以使用此参数指定对应的行,也可以使用正则表达式(python正则),表示将文本插入在符合正则表达式的行的后面,如果有多行文本都能够匹配对应的正则表达式,则以最后一个满足正则的行为准,此参数的值还可以设置为EOF,表示将文本插入到文档末尾。
-
insertbefore
该参数的值设置为BOF时,表示将文本插入到文档开头。
将文本插入在某一行的前面,可以使用此参数指定对应的行,也可以使用正则表达式(python正则),表示将文本插入在符合正则表达式的行的前面,如果有多行文本都能够匹配对应的正则表达式,则以最后一个满足正则的行为准, -
backup
是否在修改文件之前对文件进行备份。 -
create
当要操作的文件并不存在时,是否创建对应的文件。
lineinfile模块
使用该模块,能确保”某一行文本”存在于指定的文件中,或者确保从文件中删除指定的”文本”(即确保指定的文本不存在于文件中),还可以根据正则表达式,替换”某一行文本”。
案例
一、实验前的准备
创建测试文件
$ cat /testdir/test
Hello ansible,Hiiii
lineinfile -
Ensure a particular line is in a file,
lineinfile -
or replace an existing line using a back-referenced regular expression.
二、相关案例
1、如果test文件中存在"test text"这行文本,则不做任何操作,如果不存在,默认在文件的末尾插入这行文本。
$ ansible db_servers -m lineinfile -a 'path=/testdir/test line="test text"'
2、使用正则替换掉开头是line的行,替换后的内容为"test text";
注意:如果匹配到多行,就只有最后一行会被替换;如果没有匹配到任意一行,那么"test text"将会插入到文件最后一行。
$ ansible db_servers -m lineinfile -a 'path=/testdir/test regexp="^line" line="test text" '
3、没有匹配到任何一行则什么也不做。
$ ansible db_servers -m lineinfile -a 'path=/testdir/test regexp="^line" line="test text" backrefs=yes '
4、根据line参数的内容删除行,如果文件中有多行都与line参数的内容相同,那么这些相同的行都会被删除。
$ ansible db_servers -m lineinfile -a 'path=/testdir/test line="lineinfile -" state=absent'
5、根据正则表达式删除对应行,如果有多行都满足正则表达式,那么所有匹配的行都会被删除
$ ansible db_servers -m lineinfile -a 'path=/testdir/test regexp="^lineinfile" state=absent'
6、将backrefs设置为yes,表示开启支持后向引用。
举个例子,使用正则表达式可以将test示例文件中的”Hello ansible,Hiiii”替换成”Hiiii”,这里的"\2"相当于引用了前面的第二个(H.{4}),即Hiiii;
如果不设置backrefs=yes,则不支持后向引用,那么”Hello ansible,Hiiii”将被替换成”\2″。
$ ansible db_servers -m lineinfile -a 'path=/testdir/test regexp="(H.{4}).*(H.{4})" line="\2" backrefs=yes'
常用参数
path、line、state、insertafter、insertbefore、backup、create参考blockinfile模块参数说明即可,这里讲以下两个参数:
-
regexp
使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除。 -
backrefs
默认情况下,使用正则替换文本时,如果正则存在分组,在line参数中不能对正则中的分组进行引用,如果需要引用,需要设置backrefs=yes即可,详见案例6
参考资料:
转载于朱老师博客

浙公网安备 33010602011771号