首页/系统与基础设施/自动化运维速查/行编辑与块编辑模块的取舍
Ansible 核心70 条

行编辑与块编辑模块的取舍

lineinfile 用正则改单行,blockinfile 用标记维护多行块并整块替换;单行键值选前者,成组多行选后者,整份配置完全由 Ansible 掌管时用 template 更省事。

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​‌‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌​‌​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌​​‌‌​‌​​‌​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌‌​​‌‌‌​​‌‌​​‌​‌‌​‌​‌‌​​​‌​​‌‌​‌‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌​‌​‌‌​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌​​‌‌​‌​​‌​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌​​​‌‌‌​​‌​​‌‌​​​​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌​‌‌‌‌​‌‌​​‌‌​​‌‌​​‌‌​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

行编辑与块编辑

lineinfile 用正则定位单行,做存在即替换、不存在即插入的增删改;blockinfile 把多行内容包在一个带标记的区块里,每次运行按标记整块替换。前者适合天然单行的键值参数,后者适合必须一起存在的成组配置。判断依据是目标内容会不会天然分成多行、以及是否需要整块删除。

基本信息

模块名ansible.builtin.lineinfile / ansible.builtin.blockinfile
关键参数regexp、line、backrefs / block、marker、insertafter
幂等依据行是否命中或块标记是否存在
默认标记# BEGIN ANSIBLE MANAGED BLOCK 与对应 END 行

典型使用场景

  • 改单行参数(如 sshd_config 的 PermitRootLogin)用 lineinfile
  • 写多行内核参数、limits 配置用 blockinfile
  • 整份配置完全由 Ansible 掌管时改用 template,避免逐行拼装
  • 要保留原文件里人工维护的内容时,两者都只做原地插入
  • 回收变更用 state: absent 删行或删块

两种模块的用法

两种模块的用法
- name: 单行参数用 lineinfile  # 正则定位,可重复执行
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^#?\s*PermitRootLogin'
    line: 'PermitRootLogin no'
  notify: reload sshd

- name: 多行块用 blockinfile  # 按 marker 整块替换
  ansible.builtin.blockinfile:
    path: /etc/security/limits.conf
    marker: '# {mark} ANSIBLE MANAGED NOFILE'
    block: |
      * soft nofile 65535
      * hard nofile 65535

选型对照

需求推荐模块原因
单行键值lineinfile正则精确定位,改动面小
多行成组blockinfile标记保证整块一致,可整体删除
整份文件托管template文件内容由模板完全决定
保留人工内容lineinfile / blockinfile原地插入,不重写全文
regexp 命中多行时 lineinfile 会替换所有匹配行;只想改最后一处可用 backrefs 配合更严格的正则,或先手工确认文件中匹配数量。
blockinfile 的 marker 被手工改动或删除后,模块找不到标记会追加新块,同一份配置出现重复段落,且原块不再受管。

幂等从哪里来

lineinfile 的幂等来自“正则命中就替换、不命中就插入”,blockinfile 的幂等来自“找到标记就替换整块、找不到就追加”。两者都只改目标位置,不重写整个文件,所以适合接管那种一半由软件包生成、一半由人手工维护的配置文件。把整个文件完全交给 Ansible 的场景更适合 template:内容全部由模板渲染结果决定,不存在遗留旧行的不确定性。

写入前的自检:lineinfile 与 blockinfile 都支持 validate 参数,可以把“语法检查命令 + 临时文件占位符”传进去,校验不通过时保留原文件并报错,避免把服务改到起不来。

带校验的写入

带校验的写入
- name: 改完先校验再落盘  # 校验失败则保留原文件
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^PermitRootLogin'
    line: 'PermitRootLogin no'
    validate: '/usr/sbin/sshd -t -f %s'
    backup: true   # 保留一份带时间戳的备份用于回滚

文件被改了怎么办

  • 先用 grep 数一遍目标行或标记块出现几次,确认没有历史遗留
  • 模板渲染类改动用 diff 模式先看将要改什么,再决定是否执行
  • 人工临时改过的参数,改动前记入变更单,避免下次跑 playbook 被覆盖而无人知晓
  • 同一份配置的多个改动合并到一个通知项上,减少服务被反复重启的次数

易错点

  • 在 lineinfile 的 line 里塞入换行符写多行内容,会得到格式错乱的单行,应改用 blockinfile
  • 同一文件既被 lineinfile 逐行改又被 template 整体覆盖,两者互相回滚,改动表现随机
  • regexp 过宽(缺少 ^ 锚点)命中注释行与其他匹配项,一次改掉多处非目标行
  • 删除时忘记 state: absent,配置只增不减,跑得越久文件越乱
  • 删除块的 marker 与创建时写法不一致,旧块残留成为僵尸配置

数据来源与参考

  • Ansible 官方模块文档 ansible.builtin.lineinfile
  • Ansible 官方模块文档 ansible.builtin.blockinfile
  • OpenSSH 手册 sshd_config(5)

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/automation/lineinfile-vs-blockinfile-tradeoff.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​‌‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌​‌​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌​​‌‌​‌​​‌​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌‌​​‌‌‌​​‌‌​​‌​‌‌​‌​‌‌​​​‌​​‌‌​‌‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌​‌​‌‌​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌​​‌‌​‌​​‌​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌​​​‌‌‌​​‌​​‌‌​​​​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌​‌‌‌‌​‌‌​​‌‌​​‌‌​​‌‌​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​