利用lineinfile 添加dns 解析
lineinfile模块用于在源文件中插入、删除、替换行,和sed命令的功能类似,也支持正则表达式匹配和替换。
---
- name: add DNS for each
hosts: all
gather_facts: true
tasks:
- name: add DNS
lineinfile:
path: "/etc/hosts"
line: "{{item}} {{hostvars[item].ansible_hostname}}"
when: item != inventory_hostname
loop: "{{ play_hosts }}"
lineinfile 字面意思为“行在文件中”
行的添加
---
- name: test inlinefile
hosts: localhost
gather_facts: false
tasks:
- lineinfile:
path: "a.txt"
line: "this line must in"
如果 a.txt 中没有 this line must in 就添加到最后一行
如果再次执行,则不会再次追加此行。因为lineinfile模块的state参数默认值为present,它能保证幂等性,当要插入的行已经存在时则不会再插入。
如果要移除某行,则设置state参数值为absent即可。下面的任务会移除a.txt中所有的”this line must not in”行(如果多行则全部移除)。
- lineinfile:
path: "a.txt"
line: "this line must not in"
state: absent
行前和行后插入
如果想要在某行前、某行后插入指定数据行,则结合insertbefore和insertafter。例如:
- lineinfile:
path: "a.txt"
line: "LINE1"
insertbefore: '^para.* 2'
- lineinfile:
path: "a.txt"
line: "LINE2"
insertafter: '^para.* 2'
注意,insertbefore和insertafter指定的正则表达式如果匹配了多行,则默认选中最后一个匹配行,然后在被选中的行前、行后插入。如果明确要指定选中第一次匹配的行,则指定参数firstmatch=yes:
- lineinfile:
path: "a.txt"
line: "LINE1"
insertbefore: '^para.* 2'
firstmatch: yes
此外,对于insertbefore,如果它的正则表达式匹配失败,则会插入到文件的尾部。
行替换
lineinfile还可以替换行,使用regexp参数指定要匹配并被替换的行即可,默认替换最后一个匹配成功的行。
- lineinfile:
path: "a.txt"
line: "LINE1"
regexp: '^para.* 2'
play_hosts和hostvars变量
inventory_hostname变量已经使用过几次了,它表示当前正在执行任务的主机在inventory中定义的名称。在此示例中,inventory中的主机名都是IP地址。
play_hosts和hostvars是Ansible的预定义变量,执行任务时可以直接拿来使用,不过在Ansible中预定义变量有专门的称呼:魔法变量(magic variables)。Ansible支持不少魔法变量,详细信息参见官方手册:https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html#magic
首先是play_hosts变量,它存储当前play所涉及的所有主机列表,但连接失败或执行任务失败的节点不会留在此变量中。
例如,某play指定了hosts: all,那么执行这个play时,play_hosts中就以列表的方式存储了all组中的所有主机名。
hostvars变量用于保存所有和主机相关的变量,通常包括inventory中定义的主机变量和gather_facts收集到的主机信息变量。hostvars是一个key/value格式的字典(即hash结构、对象),key是每个节点的主机名,value是该主机对应的变量数据。
例如,在inventory中有一行:
192.168.200.27 myvar="hello world"
如果要通过hostvars来访问该主机变量,则使用hostvars['192.168.200.27'].myvar。
因为gather_facts收集的主机信息也会保存在hostvars变量中,所以也可以通过hostvars去访问收集到的信息。gather_facts中收集了非常多的信息,目前只需记住此处所涉及的ansible_hostname即可,它保存的是收集目标主机信息而来的主机名,不是定义在Ansible端inventory中的主机名(因为可能是IP地址)。
再者,由于hostvars中保存了所有目标主机的主机变量,所以任何一个节点都可以通过它去访问其它节点的主机变量。比如示例中hostvars[item].ansible_hostname访问的是某个主机的ansible_hostname变量。
再来看互相添加DNS解析记录的示例:
- name: add DNS
lineinfile:
path: "/etc/hosts"
line: "{{item}} {{hostvars[item].ansible_hostname}}"
when: item != inventory_hostname
loop: "{{ play_hosts }}"