【问题标题】:Ansible uncomment line in file文件中的 Ansible 取消注释行
【发布时间】:2017-02-02 11:38:25
【问题描述】:

我想使用 Ansible 取消注释文件 sshd_config 中的一行,并且我有以下工作配置:

- name: Uncomment line from /etc/ssh/sshd_config
    lineinfile:
      dest: /etc/ssh/sshd_config
      regexp: '^#AuthorizedKeysFile'
      line: 'AuthorizedKeysFile    .ssh/authorized_keys'

但是,此配置仅在行以 #AuthorizedKeysFile 开头时才有效,但如果行以 # AuthorizedKeysFile# AuthorizedKeysFile 开头(# 和单词之间的空格)则不起作用。

如何配置正则表达式,使其不考虑“#”之后的任何数量的空格?


我尝试在“#”之后添加另一个带有空格的 lineinfile 选项,但这不是一个好的解决方案:

- name: Uncomment line from /etc/ssh/sshd_config
    lineinfile:
      dest: /etc/ssh/sshd_config
      regexp: '# AuthorizedKeysFile'
      line: 'AuthorizedKeysFile    .ssh/authorized_keys'

【问题讨论】:

  • 请分享您尝试了什么?

标签: linux ansible


【解决方案1】:

如果您在“#”字符后需要零个或多个空格,则以下内容就足够了:

- name: Uncomment line from /etc/ssh/sshd_config
    lineinfile:
      dest: /etc/ssh/sshd_config
      regexp: '^#\s*AuthorizedKeysFile.*$'
      line: 'AuthorizedKeysFile    .ssh/authorized_keys'

对原始代码的修改是在正则表达式中添加\s*.*$

解释:

\s - 匹配空格(空格、制表符、换行符和换页符)

* - 指定它左边的表达式 (\s) 在匹配中可以有零个或多个实例

.* - 匹配零个或多个任意字符

$ - 匹配行尾

【讨论】:

  • +:它将在所需的行上工作,而不是在可能的 cmets 中。 -: 它不会以 ok 状态结束。
  • 它不应该在正常状态下完成,因为它已经更改了文件。第一次运行它会改变。第二次运行它将被跳过,因为它与正则表达式不匹配。
  • 我不知道为什么这很重要?
  • 这是一个反例,说明如何用 Ansible 或任何语言做事。值的更改需要手动检查和重写代码逻辑。
  • 我发现您需要添加“backrefs=yes”,否则在后续播放中它会将行添加到文件末尾。我正在使用 ansible 2.2.1.0。见stackoverflow.com/questions/33184126/…
【解决方案2】:

首先,您使用了错误的语言。使用 Ansible,您无需告诉它要做什么,而是定义所需的状态。所以不应该是Uncomment line form /etc/ssh/sshd_config,而是Ensure AuthorizedKeysFile is set to .ssh/authorized_keys

其次,初始状态是什么并不重要(如果该行被注释)。您必须指定一个唯一的字符串来标识该行。

使用sshd_config 这是可能的,因为AuthorizedKeysFile 指令在文件中只出现一次。对于其他配置文件,这可能会更加困难。

- name: Ensure AuthorizedKeysFile is set to .ssh/authorized_keys
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: AuthorizedKeysFile
    line: 'AuthorizedKeysFile    .ssh/authorized_keys'

它将匹配任何包含AuthorizedKeysFile 字符串的行(无论它是否被注释,或者有多少空格)并确保整行是:

AuthorizedKeysFile .ssh/authorized_keys

如果行不同,Ansible 将报告“已更改”状态。

在第二次运行时,Ansible 将再次找到AuthorizedKeysFile 并发现该行已经处于所需状态,因此它将以“ok”状态结束任务。


对上述任务的一个警告是,如果任何行包含注释,例如真实的、有意的注释(例如,包含字符串 AuthorizedKeysFile 的英文解释),Ansible 将用指定的值替换该行在line

【讨论】:

  • +:在第二次运行时,Ansible 将再次找到 AuthorizedKeysFile 并发现该行已处于所需状态,因此它将以“ok”状态结束任务。 -:对上述任务的一个警告:如果任何行包含注释,Ansible 可能会将该行替换为行中指定的值。
  • 除非您知道自己在做什么,否则不应使用 Ansible 修改现有文件。改用模板。
  • 模板最适合完整文件。在修改文件的某些部分时,lineinfile 是完全可以接受的,事实上这就是它的目的。
  • 对不起,但如果你使用模板以外的任何东西来实现像sshd_config 这样对安全至关重要的东西,你就是在自找麻烦。总的来说,这也是一个错误的想法。文件是否“已满”并不重要,重要的是有多少单独的进程(角色/播放/外部脚本)需要修改单个配置文件的不同部分。
  • # AuthorizedKeysFile - used to show an example where the regex replaces a legitimate comment (this one)
【解决方案3】:

@techraf 指出,在 99% 的情况下,配置文件的完整模板几乎总是更好。

我做过lineinfile 的时间包括由其他进程管理的奇怪而美妙的配置文件,或者我还不完全理解的配置文件的懒惰,并且可能因发行版/版本而异,我不想维护所有的变种......但是。

继续学习更多 Ansible... 这很棒,因为您可以从原始 bash shell 命令一直迭代到最佳实践。

lineinfile 模块

仍然很高兴看到如何最好地配置管理一个或两个设置,只是稍微好一点:

tasks:
- name: Apply sshd_config settings
  lineinfile:
    path: /etc/ssh/sshd_config
    # might be commented out, whitespace between key and value
    regexp: '^#?\s*{{ item.key }}\s'
    line: "{{ item.key }} {{ item.value }}"
    validate: '/usr/sbin/sshd -T -f %s'
  with_items:
  - key: MaxSessions
    value: 30
  - key: AuthorizedKeysFile    
    value: .ssh/authorized_keys
  notify: restart sshd

handlers:
- name: restart sshd
  service: 
    name: sshd
    state: restarted
  • validate如果更改无效,请不要进行更改
  • notify/handlers正确的方法是只在最后重启一次
  • with_items(很快变成loop)如果你有多个设置
  • ^#? 设置可能被注释掉 - 查看其他答案
  • \s*{{ item.key }}\s 不会匹配其他设置(即SettingA 无法匹配NotSettingASettingAThisIsNot

仍然可能会破坏像 # AuthorizedKeysFile - is a setting 这样的评论,因为可能存在像 AuthorizedKeysFile /some/path # is a setting 这样的设置...重新阅读警告。

模板模块

- name: Configure sshd
  template:
    src: sshd_config.j2
    dest: /etc/ssh/sshd_config
    owner: root
    group: root
    mode: "0644"
    validate: '/usr/sbin/sshd -T -f %s'
  notify: restart sshd
handlers:
- name: restart sshd
  service: 
    name: sshd
    state: restarted

多发行版支持

如果您不是懒于支持所有发行版,请参阅此提示

- name: configure ssh
  template: src={{ item }} dest={{ SSH_CONFIG }} backup=yes
  with_first_found:
    - "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.sshd_config.j2"
    - "{{ ansible_distribution }}.sshd_config.j2"

https://ansible-tips-and-tricks.readthedocs.io/en/latest/modifying-files/modifying-files/

(需要使用first_found 查找更新为loop

【讨论】:

  • 这个答案值得更多的赞成,这个 lineinfile 示例是一种非常好的和干净的方式来维护配置文件中可能会更改的许多键/值样式设置以及您希望上游更改的位置无需维护自己的模板,感谢@KCD!
【解决方案4】:

是否可以使用replace 模块实现相同的目标。

https://docs.ansible.com/ansible/latest/modules/replace_module.html

- name: Uncomment line from /etc/ssh/sshd_config
  replace:
    path: /etc/ssh/sshd_config
    regexp: '^\s*#+AuthorizedKeysFile.*$'
    replace: 'AuthorizedKeysFile    .ssh/authorized_keys'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多