lineinfile 是 Ansible 的一个非常实用的模块,它可以使用 Python 的正则表达式确保一行特定的文本存在(state=present)或者不存在(state=absent)于指定的文件中。
path 参数:
必须指定的参数。
和 file 模块的 path 参数一样,指定要操作的文件。
别名:dest, destfile, name。
state 参数:
- 确保某一行存在(state=present,替换行)或者不存在(state=absent,删除行)。
- 默认值为 present。
regexp 参数:
- 使用 Python 的正则表达式语法匹配文件中的每一行。
- 替换行(state=present)时,如果有多行文本都匹配,只有最后面被匹配到的那行文本会被替换。
- 删除行(state=absent)时,如果有多行文本都匹配,这么这些行都会被删除。
- 如果没有匹配的行,则根据insertbefore或insertafter参数的设置添加指定的行。
- 替换行时,必须确保正则表达式同时匹配修改前和被line替换后的行来保证语句的幂等性。
line 参数:
- 指定的一行需要添加到文件中的文本。
- 替换行(state=present)时,必须指定该参数。
- 如果设置了backrefs参数,还包含向后引用。
- 别名:value。
backrefs 参数:
- 替换行(state=present)时使用。
- 值为yes或no,默认值no。
- 如果指定了该参数,insertafter和insertbefore参数会被忽略。
- 默认值为no,如果没有匹配,则添加一行line。如果匹配了,则把匹配的内容替换为line的内容。
- 值为yes时,表示开启后向引用,如果没有匹配,则文件保持不变。如果匹配了,把匹配内容替被换为line的内容。
insertafter 参数:
- 替换行(state=present)时使用。
- 值为EOF或者正则表达式,默认值为EOF,表示End Of File,插入到文件的末尾。
- 如果设置为正则表达式,默认将文本插入到正则表达式匹配的最后一行之后;如果指定了firstmatch=yes参数,则插入到匹配的第一行之后。
- 如果设置为正则表达式,但是没有匹配到任何行,则插入到文件末尾。
- 如果同时指定了regexp和insertafter参数,仅当regexp没有匹配成功时insertafter参数才会生效。
- 当使用backrefs参数时,此参数会被忽略。
insertbefore 参数:
- 替换行(state=present)时使用。
- 值为BOF或者正则表达式,默认值为BOF,表示Begin Of File,插入到文件的开头。
- 如果设置为正则表达式,默认将文本插入到正则表达式匹配的最后一行之前;如果指定了firstmatch=yes参数,则插入到匹配的第一行之前。
- 如果设置为正则表达式,但是没有匹配到任何行,则插入到文件开头。
- 如果同时指定了regexp和insertbefore参数,仅当regexp没有匹配成功时insertbefore参数才会生效。
- 当使用backrefs参数时,此参数会被忽略。
firstmatch 参数:
- 值为yes或no,默认值no。
- 和insertafter、insertbefore参数一起使用。
- 值为yes时,表示insertafter、insertbefore参数使用正则表达式匹配的第一行而不是最后一行。
validate 参数:
- 修改文件之前进行校验。
- 使用“%s”表示path参数指定的需要修改的文件。
file模块的所有参数,常用的有:
- backup:是否在修改文件之前对文件进行备份。
- create :yes:当要操作的文件不存在时,创建对应的文件;默认为no:当要操作的文件不存在时,语句报错。
- mode:文件的属性。
- owner:文件的属主。
- group:文件的属组。
2、lineinfile 模块使用示例
参考lineinfile – Manage lines in text files
1、确保 SELinux 设置为 enforcing 状态。SELinux 配置文件为/etc/selinux/config,将正则表达式^SELINUX=匹配的最后一行修改为SELINUX=enforcing:
- name: Ensure SELinux is set to enforcing mode
lineinfile:
path: /etc/selinux/config
regexp: '^SELINUX='
line: SELINUX=enforcing
2、确保 sudoers 配置文件中不存在用户组 wheel。sudoers 配置文件为/etc/sudoers,删除该文件中匹配正则表达式^%wheel的所有行:
- name: Make sure group wheel is not in the sudoers configuration
lineinfile:
path: /etc/sudoers
state: absent
regexp: '^%wheel'
3、将 hosts 文件/etc/hosts中正则表达式^127\.0\.0\.1匹配的最后一行修改为127.0.0.1 localhost,同时修改文件属主和属组为root,属性为0644:
- name: Replace a localhost entry with our own
lineinfile:
path: /etc/hosts
regexp: '^127\.0\.0\.1'
line: 127.0.0.1 localhost
owner: root
group: root
mode: '0644'
4、修改默认 Apache 的监听端口为 8080。Apache 的配置文件/etc/httpd/conf/httpd.conf,将正则表达式^Listen匹配的最后一行修改为Listen 8080;如果没有匹配的行,在正则表达式^#Listen匹配的最后一行之后添加Listen 8080;如果还是没有匹配的行,直接在文件末尾添加Listen 8080:
- name: Ensure the default Apache port is 8080
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen '
insertafter: '^#Listen '
line: Listen 8080
5、在/etc/services文件中添加自定义描述。修改/etc/services文件中正则表达式^# port for http匹配的最后一行为# port for http by default;如果没有匹配的行,在正则表达式^www.*80/tcp匹配的最后一行之前添加# port for http by default;如果还是没有匹配的行,直接在文件开头添加# port for http by default:
- name: Ensure we have our own comment added to /etc/services
lineinfile:
path: /etc/services
regexp: '^# port for http'
insertbefore: '^www.*80/tcp'
line: '# port for http by default'
6、确保文件/tmp/testfile中存在行192.168.1.99 foo.lab.net foo且仅有一行,如果文件不存在则自动创建:
- name: Add a line to a file if the file does not exist, without passing regexp
lineinfile:
path: /tmp/testfile
line: 192.168.1.99 foo.lab.net foo
create: yes
7、精确设置 JBoss 的内存。假设 ${xms} 值为 2000,则如下的示例将替换-Xmx3550m -Xms3550m -Xmn2g -Xss128k为-Xmx3550m -Xms2000m -Xmn2g -Xss128k:
# NOTE: Yaml requires escaping backslashes in double quotes but not in single quotes
- name: Ensure the JBoss memory settings are exactly as needed
lineinfile:
path: /opt/jboss-as/bin/standalone.conf
regexp: '^(.*)Xms(\\d+)m(.*)$'
line: '\1Xms${xms}m\3'
backrefs: yes
- 这里backrefs = yes,如果没有匹配成功,则不会修改/opt/jboss-as/bin/standalone.conf文件内容。
8、设置用户组 ADMIN 无需密码即可使用sudo命令,并且使用/usr/sbin/visudo -cf /etc/sudoers命令校验配置文件:
# NOTE: Fully quoted because of the ': ' on the line. See the Gotchas in the YAML docs.
- name: Validate the sudoers file before saving
lineinfile:
path: /etc/sudoers
state: present
regexp: '^%ADMIN ALL='
line: '%ADMIN ALL=(ALL) NOPASSWD: ALL'
validate: /usr/sbin/visudo -cf %s
学会了上面几个常用的参数之后,就可以使用 lineinfile 模块编写更复杂的 Ansible 行替换语句了。