Ansible循环生成sudoers文件异常,求正确实现方案
问题原因分析
你的Playbook问题出在content字段的Jinja2循环逻辑:你遍历了整个sudoers_include字典的所有键值对,导致不管循环到哪个文件(比如sudofile1),都会把所有sudofile的规则全部写入目标文件,这就是为什么生成的文件包含所有规则的原因。
正确实现方式
方法1:修正copy模块的循环逻辑
不需要遍历整个字典,直接利用循环项item.value获取当前文件对应的规则列表即可:
--- - name: main hosts: all become: true vars: sudoers_include: sudofile1: - "%kombit ALL=NOPASSWD: /usr/local/bin/create_sftp_dirs.sh" - "%kombit ALL=NOPASSWD: /usr/local/bin/add_public_key.sh" - "%kombit ALL=NOPASSWD: /usr/local/bin/remove_sftp_dirs.sh" - "%kombit ALL=NOPASSWD: /usr/local/bin/lock_file.sh" - "%kombit ALL=NOPASSWD: /usr/local/bin/unlock_file.sh" sudofile2: - "%admin1 ALL=NOPASSWD: /usr/local/bin/create_sftp_dirs.sh" - "%admin2 ALL=NOPASSWD: /usr/local/bin/add_public_key.sh" tasks: - copy: dest: "/tmp/{{ item.key }}" content: | {%- for rule in item.value -%} {{ rule }} {%- endfor -%} loop: "{{ sudoers_include | dict2items }}"
这样每个文件只会写入自身对应的规则列表,不会混入其他文件的内容。
方法2:使用template模块(推荐复杂场景)
如果后续需要给sudoers文件添加头部注释、权限校验逻辑,或者规则格式需要更复杂的渲染,template模块会更灵活:
- 创建模板文件(例如
sudoers.j2):
# 自动生成的sudoers规则文件,请勿手动修改 {%- for rule in rules -%} {{ rule }} {%- endfor -%}
- 修改Playbook调用模板:
--- - name: main hosts: all become: true vars: sudoers_include: sudofile1: - "%kombit ALL=NOPASSWD: /usr/local/bin/create_sftp_dirs.sh" - "%kombit ALL=NOPASSWD: /usr/local/bin/add_public_key.sh" - "%kombit ALL=NOPASSWD: /usr/local/bin/remove_sftp_dirs.sh" - "%kombit ALL=NOPASSWD: /usr/local/bin/lock_file.sh" - "%kombit ALL=NOPASSWD: /usr/local/bin/unlock_file.sh" sudofile2: - "%admin1 ALL=NOPASSWD: /usr/local/bin/create_sftp_dirs.sh" - "%admin2 ALL=NOPASSWD: /usr/local/bin/add_public_key.sh" tasks: - template: src: sudoers.j2 dest: "/tmp/{{ item.key }}" loop: "{{ sudoers_include | dict2items }}" vars: rules: "{{ item.value }}"
模块选择建议
- 若只是简单将列表内容逐行写入文件,用copy模块加循环足够简洁;
- 若需要复杂的格式渲染、注释添加或逻辑判断,优先用template模块,扩展性更强。
内容的提问来源于stack exchange,提问作者johnny bravo
相关产品推荐
相关产品推荐

