Ansible lineinfile — изменить строку

#ansible #ansible-playbook #ansible-2.x

#ansible #ansible-2.x

Вопрос:

Я новичок в Ansible и пытаюсь изменить строку, /etc/default/grub чтобы включить аудит.

Мне нужно добавить audit=1 в кавычки где-нибудь в строке, которая выглядит как:

 GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap biosdevname=0 net.ifnames=0 rhgb quiet net.ifnames=0"
  

До сих пор мне удалось удалить строку, и у меня осталось только

 net.ifnames=0, audit=1
  

когда я использую что-то вроде

 lineinfile:
  state: present
  dest: /etc/default/grub
  backrefs: yes
  regexp: "net.ifnames=0"
  line: "1 audit=1"
  

Можно ли это сделать?

Ответ №1:

Вы можете попробовать это:

 - lineinfile:
    state: present
    dest: /etc/default/grub
    backrefs: yes
    regexp: '^(GRUB_CMDLINE_LINUX=(?!.* audit)"[^"] )(".*)'
    line: '1 audit=12'
  

Это добавит audit=1 (с начальным пробелом) непосредственно перед закрытием двойных кавычек. Он не будет совпадать без двойных кавычек.
И он пытается быть идемпотентным: не соответствует строкам, которые уже есть audit (с начальным пробелом) после GRUB_CMDLINE_LINUX= .

Я бы рекомендовал использовать такие сайты, как regex101, чтобы сначала протестировать ваши регулярные выражения (там также есть режим подстановки).
Когда вы будете удовлетворены результатом, продолжайте выполнение задачи Ansible.

Комментарии:

1. @Джефф Билбро — если вам нужно добавить его только к строкам, имеющим «net.ifnames = 0», вам нужно добавить это в строку регулярного выражения, предоставленную Константином Сурворовым. Вероятно, что-то вроде этого: regexp: '^(GRUB_CMDLINE_LINUX=.*net.iframes=0.*(?!.*audit)"[^"] )(".*)'

2. Чтобы это также работало, когда GRUB_CMDLINE_LINUX пуст, вы можете использовать ^(GRUB_CMDLINE_LINUX=(?!.*audit)"[^"]*)(".*)

3. Для всех, кто еще попадает сюда с несколько связанным вопросом: в Ubuntu 18.04 я хотел использовать GRUB_CMDLINE_LINUX_DEFAULT= вместо GRUB_CMDLINE_LINUX= , потому что, похоже, это тот, который используется обычно (где все остальные параметры).

4. Кто-нибудь может объяснить, почему это разрешает любые символы после второй двойной кавычки? Разве правильная строка не начинается и не заканчивается двойными кавычками (или вообще не содержит двойных кавычек в строке)?

5. может ли эта строка быть добавлена в отдельный файл в /etc/default/grub.d/ каталоге и иметь тот же эффект?

Ответ №2:

Я хотел убедиться, что для параметра также установлено правильное значение, поэтому я использовал этот вызов замены:

 replace:
  path: /etc/default/grub
  regexp: '^(GRUB_CMDLINE_LINUX=(?:(?![" ]{{ option | regex_escape }}=).)*"?)s*(?:{{ option | regex_escape }}=S s*)?(.*")$'
  replace: '1 {{ option }}={{ value }}2'
vars:
  option: audit
  value: 1
  

Это работает, если опция не присутствовала ранее, если она была, но имела неправильную опцию (тогда изменяется только значение) и если вся строка была пустой (но тогда добавляется пробел перед опцией). Кроме того, он используется regex_escape для корректной работы с именами параметров, которые содержат точки и тому подобное, и вам нужно указать их только один раз.

Комментарии:

1. Очень, очень приятно!

2. С регулярным выражением есть одна проблема: если параметр позиционируется как первый после кавычки, например: GRUB_CMDLINE_LINUX="elevator=noop" тогда ваше регулярное выражение будет разжевывать начальную кавычку, а результирующая строка заканчивается без первой кавычки, и это нарушает grub. Это исправление: regexp: '^(GRUB_CMDLINE_LINUX="(?:(?!{{ option | regex_escape }}=).)*)([ ]{{ option | regex_escape }}=w [ ])?[ ]?(?:{{ option | regex_escape }}=S )?(.*")$' и, наконец, replace: '1{{ option }}={{ value }}3'

3. Вы правы, исправили это (хотя и по-другому, поскольку ваш ответ, вероятно, соответствует частичным параметрам, например ata.elevator , или что-то в этом роде)