ansible.builtin.blockinfile 模块 – 插入/更新/移除由标记行包围的文本块

注意

此模块是 ansible-core 的一部分,包含在所有 Ansible 安装中。在大多数情况下,即使不指定 collections 关键字,您也可以使用简短的模块名称 blockinfile。但是,我们建议您使用 完全限定集合名称 (FQCN) ansible.builtin.blockinfile,以便轻松链接到模块文档并避免与可能具有相同模块名称的其他集合冲突。

概要

  • 此模块将插入/更新/移除由可自定义标记行包围的多行文本块。

参数

参数

注释

append_newline

布尔值

在 ansible-core 2.16 中添加

如果插入块末尾没有空行,则向插入块追加一个空行。

请注意,当 state 设置为 absent 时,不考虑此属性。

选项

  • false ← (默认)

  • true

attributes

别名:attr

字符串

生成的 filesystem 对象应具有的属性。

要查看支持的标志,请查看目标系统上 chattr 的手册页。

此字符串应包含与 lsattr 显示的顺序相同的属性。

= 运算符被假定为默认值,否则需要在字符串中包含 +- 运算符。

backup

布尔值

创建一个包含时间戳信息的备份文件,以便您可以找回原始文件(如果您不小心错误地覆盖了它)。

选项

  • false ← (默认)

  • true

block

别名:content

字符串

要插入到标记行内的文本。

如果它缺失或为空字符串,则该块将被移除,就像 state 指定为 absent 一样。

默认值: ""

create

布尔值

如果文件不存在,则创建一个新文件。

选项

  • false ← (默认)

  • true

group

字符串

应该拥有 filesystem 对象的组的名称,就像传递给 chown 一样。

如果未指定,它将使用当前用户的当前组,除非您是 root 用户,在这种情况下,它可以保留之前的拥有者。

insertafter

字符串

如果指定且未找到 begin/ending marker 行,则该块将插入到指定正则表达式的最后一次匹配之后。

可以使用一个特殊值;EOF 用于将块插入到文件的末尾。

如果指定的正则表达式没有匹配项或没有传递值,则将使用 EOF 代替。

正则表达式中多行标志 (?m) 的存在控制匹配是逐行进行还是多行进行。此行为是在 ansible-core 2.14 中添加的。

insertbefore

字符串

如果指定且未找到 begin/ending marker 行,则该块将插入到指定正则表达式的最后一次匹配之前。

可以使用一个特殊值;BOF 用于将块插入到文件的开头。

如果指定的正则表达式没有匹配项,则该块将插入到文件的末尾。

正则表达式中多行标志 (?m) 的存在控制匹配是逐行进行还是多行进行。此行为是在 ansible-core 2.14 中添加的。

marker

字符串

标记行模板。

{mark} 将被替换为 marker_begin (默认=BEGIN) 和 marker_end (默认=END) 中的值。

使用没有 {mark} 变量的自定义标记可能会导致在后续 playbook 运行中重复插入块。

不支持多行标记,这将导致在后续 playbook 运行中重复插入块。

模块会自动将换行符附加到 marker_beginmarker_end

默认值: "# {mark} ANSIBLE MANAGED BLOCK"

marker_begin

字符串

这将插入到起始 Ansible 块 marker 中的 {mark}

默认值: "BEGIN"

marker_end

字符串

这将插入到结束 Ansible 块 marker 中的 {mark}

默认值: "END"

mode

任意

生成的 filesystem 对象应具有的权限。

对于习惯使用 /usr/bin/chmod 的用户,请记住模式实际上是八进制数。您必须向 Ansible 提供足够的信息才能正确解析它们。为了获得一致的结果,请引用八进制数(例如,'644''1777'),以便 Ansible 接收字符串并可以自行将字符串转换为数字。添加前导零(例如,0755)有时有效,但在循环和其他一些情况下可能会失败。

向 Ansible 提供不遵循这些规则中的任何一个的数字将导致十进制数,这将产生意外的结果。

从 Ansible 1.8 开始,模式可以指定为符号模式(例如,u+rwxu=rw,g=r,o=r)。

如果未指定mode且目标文件系统对象**不存在**,则在设置新创建的文件系统对象的模式时,将使用系统上的默认umask

如果未指定mode且目标文件系统对象**存在**,则将使用现有文件系统对象的模式。

指定mode是确保文件系统对象以正确的权限创建的最佳方法。有关更多详细信息,请参阅 CVE-2020-1736。

owner(所有者)

字符串

应拥有文件系统对象的用户的名称,如同提供给chown一样。

如果未指定,则使用当前用户,除非您是 root 用户,在这种情况下,它可以保留之前的拥有者。

指定数字用户名将被视为用户 ID 而不是用户名。避免使用数字用户名以避免混淆。

path(路径)

别名:dest、destfile、name

path(路径) / 必填

要修改的文件。

在 Ansible 2.3 之前,此选项只能用作destdestfilename

prepend_newline(添加换行符)

布尔值

在 ansible-core 2.16 中添加

如果文件中开头没有空行,则在插入的块之前添加一个空行。

请注意,当 state 设置为 absent 时,不考虑此属性。

选项

  • false ← (默认)

  • true

selevel(SELinux 安全级别)

字符串

SELinux 文件系统对象上下文的级别部分。

这是 MLS/MCS 属性,有时称为range

设置为_default时,如果可用,它将使用策略的level部分。

serole(SELinux 安全角色)

字符串

SELinux 文件系统对象上下文的角色部分。

设置为_default时,如果可用,它将使用策略的role部分。

setype(SELinux 安全类型)

字符串

SELinux 文件系统对象上下文的类型部分。

设置为_default时,如果可用,它将使用策略的type部分。

seuser(SELinux 安全用户)

字符串

SELinux 文件系统对象上下文的用户部分。

默认情况下,它使用system策略(如果适用)。

设置为_default时,如果可用,它将使用策略的user部分。

state(状态)

字符串

块是否存在。

选项

  • "absent"(不存在)

  • "present" ← (默认)

unsafe_writes(非原子写入)

布尔值

影响何时使用原子操作来防止数据损坏或目标文件系统对象的不一致读取。

默认情况下,此模块使用原子操作来防止数据损坏或目标文件系统对象的不一致读取,但有时系统配置错误或损坏,无法执行此操作。一个例子是 docker 挂载的文件系统对象,无法从容器内部以原子方式更新,只能以非原子方式写入。

此选项允许 Ansible 在原子操作失败时回退到非原子更新文件系统对象的方法(但是,它不会强制 Ansible 执行非原子写入)。

重要!非原子写入容易出现竞争条件,并可能导致数据损坏。

选项

  • false ← (默认)

  • true

validate(验证)

字符串

在将更新的文件复制到最终目标之前运行的验证命令。

使用临时文件路径进行验证,通过%s传递,如下面的示例中所示。

此外,命令以安全方式传递,因此 shell 功能(例如扩展和管道)将不起作用。

有关如何处理比此选项提供的更复杂的验证的示例,请参阅处理复杂的验证

属性

属性

支持

描述

check_mode(检查模式)

支持:完全支持

可以在 check_mode 下运行并返回更改状态预测,而无需修改目标,如果不支持,则将跳过操作。

diff_mode(差异模式)

支持:完全支持

在差异模式下,将返回有关已更改内容(或在 check_mode 下可能需要更改的内容)的详细信息。

platform(平台)

平台: posix

可以对其进行操作的目标操作系统/系列。

safe_file_operations(安全文件操作)

支持:完全支持

使用 Ansible 的严格文件操作函数来确保正确的权限并避免数据损坏。

vault(加密库)

支持:不支持

可以自动解密 Ansible 加密的 vault 文件。

注释

注意

  • 使用with_*循环时,请注意,如果未设置唯一标记,则块将在每次迭代中被覆盖。

  • 从 Ansible 2.3 开始,dest选项已更改为path作为默认值,但dest仍然有效。

  • 在 Ansible 2.5 中已删除选项follow,因为此模块修改文件的内容,因此follow=no没有意义。

  • 当一个文件中应处理多个块时,必须为每个任务更改marker

示例

# Before Ansible 2.3, option 'dest' or 'name' was used instead of 'path'
- name: Insert/Update "Match User" configuration block in /etc/ssh/sshd_config prepending and appending a new line
  ansible.builtin.blockinfile:
    path: /etc/ssh/sshd_config
    append_newline: true
    prepend_newline: true
    block: |
      Match User ansible-agent
      PasswordAuthentication no

- name: Insert/Update eth0 configuration stanza in /etc/network/interfaces
        (it might be better to copy files into /etc/network/interfaces.d/)
  ansible.builtin.blockinfile:
    path: /etc/network/interfaces
    block: |
      iface eth0 inet static
          address 192.0.2.23
          netmask 255.255.255.0

- name: Insert/Update configuration using a local file and validate it
  ansible.builtin.blockinfile:
    block: "{{ lookup('ansible.builtin.file', './local/sshd_config') }}"
    path: /etc/ssh/sshd_config
    backup: yes
    validate: /usr/sbin/sshd -T -f %s

- name: Insert/Update HTML surrounded by custom markers after <body> line
  ansible.builtin.blockinfile:
    path: /var/www/html/index.html
    marker: "<!-- {mark} ANSIBLE MANAGED BLOCK -->"
    insertafter: "<body>"
    block: |
      <h1>Welcome to {{ ansible_hostname }}</h1>
      <p>Last updated on {{ ansible_date_time.iso8601 }}</p>

- name: Remove HTML as well as surrounding markers
  ansible.builtin.blockinfile:
    path: /var/www/html/index.html
    marker: "<!-- {mark} ANSIBLE MANAGED BLOCK -->"
    block: ""

- name: Add mappings to /etc/hosts
  ansible.builtin.blockinfile:
    path: /etc/hosts
    block: |
      {{ item.ip }} {{ item.name }}
    marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.name }}"
  loop:
    - { name: host1, ip: 10.10.1.10 }
    - { name: host2, ip: 10.10.1.11 }
    - { name: host3, ip: 10.10.1.12 }

- name: Search with a multiline search flags regex and if found insert after
  blockinfile:
    path: listener.ora
    block: "{{ listener_line | indent(width=8, first=True) }}"
    insertafter: '(?m)SID_LIST_LISTENER_DG =\n.*\(SID_LIST ='
    marker: "    <!-- {mark} ANSIBLE MANAGED BLOCK -->"

作者

  • Yaegashi Takeshi (@yaegashi)