lineinfile module not acting appropriately with An

2019-03-03 03:05发布

问题:

My code is removing all instances of socket variables in my.cnf file and then repopulating the file with the correct variable and file location.

The deletion portion is working correctly, however the insert quits after the first line. So it will insert the correct 'socket' line directly under [mysqladmin] but it won't add to the remaining sections of the file.


- name: modify my.cnf setting
  hosts: dbservers
  remote_user: dbuser
  become: yes

  tasks:
  - name: delete old socket definitions
    lineinfile:
      dest: /etc/mysql/my.cnf
      regexp: "^socket "
      state: absent

  - name: add new socket variable
    lineinfile:
      dest: /etc/mysql/my.cnf
      line: "{{ item.line }}"
      insertafter: "{{ item.insertafter }}"
    with_items:
      - { line: 'socket = /mysql/run/mysqld.sock', insertafter: '^\[mysqladmin\]' }
      - { line: 'socket = /mysql/run/mysqld.sock', insertafter: '^\[mysql\]' }
      - { line: 'socket = /mysql/run/mysqld.sock', insertafter: '^\[mysqldump\]' }
      - { line: 'socket = /mysql/run/mysqld.sock', insertafter: '^\[mysqld\]' }

On an additional note, I'd like there to be a line of space between the header and the new socket declaration if that is at all possible.

I've tried with version 2.0.2 and 2.2.0 and neither are behaving as intended.

回答1:

The lineinfile works as it should (see @techraf's answer).

Your task is:

My code is removing all instances of socket variables in my.cnf file and then repopulating the file with the correct variable and file location.

Why not use replace then?

- replace:
    dest: /etc/mysql/my.cnf
    regexp: '^socket.*$'
    replace: 'socket = /mysql/run/mysqld.sock'

Keep in mind:

It is up to the user to maintain idempotence by ensuring that the same pattern would never match any replacements made.

So you may want to change regexp ^socket.*$ to something that matches only "wrong" values that should be replaced to prevent unnecessary changed state of the task.



回答2:

Ansible works exactly as intended. lineinfile module is used to ensure a particular line is in the specified file. The name of the module describes its function literally: "line in a file". It's not "lines in a file" or "line in a part of a file".

You specify only one pattern for the line:

socket = /mysql/run/mysqld.sock

so after Ansible ensured it exists (likely inserting it), all further calls to "ensure it exists" will not insert it again, because it already exists (that's how declarative programming works).

It doesn't matter that you specify a different insert_after values, because the like is the same and insert_after is not a part of the condition.

Although you don't show the exact syntax of your configuration file, it looks like an INI-style formatting (it also looks like a regular MySQL option file, which is an INI file), thus you may try using ini_file module instead.