行编辑与块编辑
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 被覆盖而无人知晓
- 同一份配置的多个改动合并到一个通知项上,减少服务被反复重启的次数