【问题标题】:Ansible: Insert line if not existsAnsible:如果不存在则插入行
【发布时间】:2021-08-07 16:32:52
【问题描述】:

我正在尝试使用 ansible 在属性文件中插入一行。 如果某些属性不存在,我想添加它,但如果文件中已存在此类属性,则不替换它。

我添加到我的 ansible 角色

- name: add couchbase host to properties
  lineinfile: dest=/database.properties regexp="^couchbase.host"  line="couchbase.host=127.0.0.1"

但这会将属性值替换回 127.0.0.1,如果它已经存在于文件中。

我做错了什么?

【问题讨论】:

    标签: ansible ansible-playbook


    【解决方案1】:

    lineinfile 模块确保文件中存在line 中定义的行,并且该行由您的regexp 标识。因此,无论您的设置已有什么值,它都会被您的新 line 覆盖。

    如果您不想覆盖该行,您首先需要测试内容,然后将该条件应用于lineinfile 模块。没有用于测试文件内容的模块,因此您可能需要使用shell 命令运行grep 并检查.stdout 的内容。像这样的东西(未经测试):

    - name: Test for line
      shell: grep -c "^couchbase.host" /database.properties || true
      register: test_grep
    

    然后将条件应用于您的lineinfile 任务:

    - name: add couchbase host to properties
      lineinfile:
        dest: /database.properties
        line: couchbase.host=127.0.0.1
      when: test_grep.stdout == "0"
    

    regexp 然后可以删除,因为您已经确定该行不存在,因此它永远不会匹配。

    但也许你正在做事从前到后。文件中的那一行来自哪里?当您使用 Ansible 管理您的系统时,应该没有其他机制会干扰相同的配置文件。也许您可以通过为您的角色添加 default 值来解决此问题?

    【讨论】:

    • 我需要向我的部署环境添加一个新属性。这包括生产和模拟服务器。我的 ansible 在 cron 和服务器启动时运行(我根据需要从图像创建模拟服务器)该属性的默认值是 localhost,但在某些服务器上,我稍后会手动更改它。我认为 ansible 可以很好地处理这样的变化
    • Ansible 将能够配置您的新服务器并配置它们。只是在您使用 lineinfile 模块的剧本中,您已指定 ansible 始终有一行 couchbase.host=127.0.0.1 并覆盖以前的值。这就是你配置它的方式。
    • 尝试使用 @udondan 提到的 when 子句
    • 我认为在 ansible 中我见证了这种方法的问题。如果 grep 找到了一些东西,那很好。但是如果 grep 什么都不返回,我会得到 "msg": "non-zero return code", "rc": 1, "start": "2019-03-09 00:50:15.184315", "stderr": "", “stderr_lines”:[],“stdout”:“”,“stdout_lines”:[]}
    • @openCivilisation 那是因为 grep 在不匹配时返回退出代码 1。 Ansible 假设非零退出代码是脚本/命令的失败,因此中止。我所做的是:shell: 'grep "my_pattern" some_file -c || true' 用于检查,然后when: test_grep.stdout == "0" 用于条件。
    【解决方案2】:

    这可以通过简单地使用lineinfilecheck_mode 来实现:

    - name: Check if couchbase.host is already defined
      lineinfile:
        state: absent
        path: "/database.properties"
        regexp: "^couchbase.host="
      check_mode: true
      changed_when: false # This just makes things look prettier in the logs
      register: check
    
    - name: Define couchbase.host if undefined
      lineinfile:
        state: present
        path: "/database.properties"
        line: "couchbase.host=127.0.0.1"
      when: check.found == 0
    
    

    【讨论】:

      【解决方案3】:

      这是我能够让它工作的唯一方法。

      - name: checking for host
        shell: cat /database.properties | grep couchbase.host | wc -l
        register: test_grep
      
      - debug: msg="{{test_grep.stdout}}"
      
      - name: adding license server
        lineinfile: dest=/database.properties line="couchbase.host=127.0.0.1"
        when: test_grep.stdout == "0"
      

      【讨论】:

      • shell: grep -c couchbase.host /database.properties,更少的二进制文件。
      【解决方案4】:

      经过漫长的“试验和错误”,我得出了这个结论:

      - name: check existence of line in the target file
        command: grep -Fxq "ip addr add {{ item }}/32 dev lo label lo:{{ app | default('app') }}" /etc/rc.local
        changed_when: false
        failed_when: false
        register: ip_test
        with_items:
          - "{{ list_of_ips }}"
      
      - name: add autostart command
        lineinfile: dest=/etc/rc.local 
                    line="ip addr add {{ item.item }}/32 dev lo label lo:{{ app | default('app') }}"
                    insertbefore="exit 0"
                    state=present
        when: item.rc == 1
        with_items:
          - "{{ ip_test.results }}"
      

      【讨论】:

        【解决方案5】:

        与此处提出的想法相同:https://stackoverflow.com/a/40890850/7231194

        步骤是:

        • 尝试替换该行。
        • 如果replace mod改变它,restore
        • 如果replace mod没有改变,添加行

        例子

        # Vars
        - name: Set parameters
          set_fact:
            ipAddress    : "127.0.0.1"
            lineSearched : "couchbase.host={{ ipAddress }}"
            lineModified : "couchbase.host={{ ipAddress }} hello"
        
        # Tasks
        - name: Try to replace the line
          replace:
            dest    : /dir/file
            replace : '{{ lineModified }} '
            regexp  : '{{ lineSearched }}$'
            backup  : yes
         register  : checkIfLineIsHere
        
        # If the line not is here, I add it
        - name: Add line
          lineinfile:
          state   : present
          dest    : /dir/file
          line    : '{{ lineSearched }}'
          regexp  : ''
          insertafter: EOF
        when: checkIfLineIsHere.changed == false
        
        # If the line is here, I still want this line in the file, Then restore it
        - name: Restore the searched line.
          lineinfile:
            state   : present
            dest    : /dir/file
            line    : '{{ lineSearched }}'
            regexp  : '{{ lineModified }}$'
          when: checkIfLineIsHere.changed
        

        【讨论】:

          【解决方案6】:

          如果您使用 backrefs,它似乎不起作用。

          以下示例不添加一行

          - name: add hosts file entry
            lineinfile:
              path: "/etc/hosts"
              regexp: "foohost"
              line:  "10.10.10.10 foohost"
              state: present
              backrefs: yes
          

          删除反向引用后,我将我的行添加到文件中

          - name: add hosts file entry
            lineinfile:
              path: "/etc/hosts"
              regexp: "foohost"
              line:  "10.10.10.10 foohost"
              state: present
          

          【讨论】:

            【解决方案7】:

            好的,这是我的幼稚解决方案......可能不是跨平台和原生 Ansible(我刚刚开始使用这个工具并且还在学习它),但肯定更短:

            - name: Update /path/to/some/file
              shell: grep -q 'regex' /path/to/some/file && echo exists || echo 'text-to-append' >> /path/to/some/file
              register: result
              changed_when: result.stdout.find('exists') == -1
            

            【讨论】:

              【解决方案8】:

              我们尝试了以下方法,效果很好。如果 syslog 文件不存在,我们的场景需要在 syslog 文件中输入“compress”。

              - name: Checking compress entry present if not add entry   
                lineinfile:
                  path: /etc/logrotate.d/syslog
                  regexp: "    compress"
                  state: present
                  insertafter: "    missingok"
                  line: "    compress"
              

              【讨论】:

                【解决方案9】:
                - name: add couchbase.host to properties, works like add or replace
                  lineinfile:
                    path: /database.properties
                    regexp: '^couchbase.host=(?!(127.0.0.1))\b'
                    line: 'couchbase.host=127.0.0.1'
                

                此代码将替换除couchbase.host=127.0.0.1 之外的任何行^couchbase.host=*,如果不存在则添加新行

                【讨论】:

                  【解决方案10】:
                  - name: add couchbase.host to properties, works like add or replace
                    lineinfile: 
                      state: present
                      dest: /database.properties 
                      regexp: '^couchbase.host'
                      line: 'couchbase.host=127.0.0.1'
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2018-09-17
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-12-17
                    • 1970-01-01
                    • 2014-06-11
                    • 1970-01-01
                    • 2023-03-21
                    相关资源
                    最近更新 更多