十一、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


参考资料:
转载于朱老师博客

posted @ 2021-06-09 15:27  努力吧阿团  阅读(227)  评论(0)    收藏  举报