为何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'
原因分析
- 正则表达式匹配失败:
regexp参数里的(ALL)未转义,正则语法中()是分组元字符,会被解析为匹配ALL而非字面量(ALL)。若目标文件中行是test3 ALL=(ALL) NOPASSWD: ALL,这个正则根本匹配不到该行,lineinfile模块找不到匹配行时,默认会将新行追加到文件末尾。 - 目标行实际不存在:如果
/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
相关产品推荐
相关产品推荐

