You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何test999的sudo规则行始终插入到/etc/sudoers文件末尾?

问题描述

需要在/etc/sudoers文件中test3 ALL=(ALL) NOPASSWD: ALL行之前插入test999 ALL=(ALL) NOPASSWD: ALL,但执行Ansible Playbook后,新行始终被追加到文件末尾。对应的Playbook代码如下:

---
- hosts: app_stage
  become: yes
  vars:
    user: test999
  tasks:
    - name: remove immutable
      file:
        path: /etc/sudoers
        attr: '-i'
    - name: change permission
      file:
        path: /etc/sudoers
        mode: 0660
    - name: Allow ‘user’ to have passwordless sudo
      lineinfile:
        dest: /etc/sudoers
        state: present
        regexp: '^test3 ALL=(ALL) NOPASSWD: ALL'
        insertbefore: '^test3 ALL=(ALL) NOPASSWD: ALL'
        line: '{{ user }} ALL=(ALL) NOPASSWD: ALL'
        validate: visudo -cf %s
    - name: change permissions back
      file:
        path: /etc/sudoers
        mode: 0440
        owner: root
        group: root
    - name: back immutable
      file:
        path: /etc/sudoers
        attr: '+i'
原因分析
  1. 正则表达式匹配失败:regexp参数里的(ALL)未转义,正则语法中()是分组元字符,会被解析为匹配ALL而非字面量(ALL)。若目标文件中行是test3 ALL=(ALL) NOPASSWD: ALL,这个正则根本匹配不到该行,lineinfile模块找不到匹配行时,默认会将新行追加到文件末尾。
  2. 目标行实际不存在:如果/etc/sudoers里本身没有^test3 ALL=(ALL) NOPASSWD: ALL这一行(比如行首有空格、大小写不一致、拼写错误),同样会触发模块的默认追加行为。
修复方案

修正lineinfile模块的正则表达式,转义特殊字符;同时确认目标行确实存在于文件中。修改后的任务代码如下:

- name: Allow ‘user’ to have passwordless sudo
  lineinfile:
    dest: /etc/sudoers
    state: present
    regexp: '^test3 ALL=\(ALL\) NOPASSWD: ALL'
    insertbefore: '^test3 ALL=\(ALL\) NOPASSWD: ALL'
    line: '{{ user }} ALL=(ALL) NOPASSWD: ALL'
    validate: visudo -cf %s

也可以简化写法,利用insertbefore直接指定正则(无需重复写regexp),不过保留regexp能确保只有目标行存在时才插入新行,避免重复添加。

内容的提问来源于stack exchange,提问作者Iceforest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 08:40:36