Is there a way to add a string to the middle of a line?
Here is the present line:
GRUB_DEFAULT="root=/dev/sda"
Should be like this:
GRUB_DEFAULT="numa_balancing=disable root=/dev/sda"
Is there a way to add a string to the middle of a line?
Here is the present line:
GRUB_DEFAULT="root=/dev/sda"
Should be like this:
GRUB_DEFAULT="numa_balancing=disable root=/dev/sda"
shell> cat /tmp/grub
GRUB_DEFAULT="root=/dev/sda"
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=2
GRUB_CMDLINE_LINUX="quiet splash net.ifnames=1 biosdevname=0 ipv6.disable=1"
WARNING: The solution below works for space-delimited items only!
Read the file to registered variable out
- command:
cmd: "cat {{ grub_file }}"
register: out
Use filter community.general.jc and parse the file. Put the declarations below as appropriate, for example, to the playbook vars
grub_file: /tmp/grub
grub_ini: "{{ out.stdout|community.general.jc('ini') }}"
grub_keys: "{{ grub_ini.keys()|list }}"
grub_vals: "{{ grub_ini.values()|map('split', ' ') }}"
grub_orig: "{{ dict(grub_keys|zip(grub_vals)) }}"
gives
grub_orig:
grub_cmdline_linux:
- quiet
- splash
- net.ifnames=1
- biosdevname=0
- ipv6.disable=1
grub_default:
- root=/dev/sda
grub_timeout:
- '2'
grub_timeout_style:
- hidden
Declare the changes you want to make. For example, create the below dictionary also in the playbook vars
grub_update:
GRUB_DEFAULT:
- "numa_balancing=disable"
Now, the module lineinfile below iterates the keys of the dictionary grub_update, concatenates unique items, and updates the configuration lines
- lineinfile:
path: "{{ grub_file }}"
regexp: '^{{ item }}.*$'
line: '{{ item }}="{{ line }}"'
loop: "{{ grub_update.keys()|list }}"
vars:
line: "{{ (grub_update[item] + grub_orig[item|lower]|d([]))|
unique|
join(' ') }}"
gives
shell> cat /tmp/grub
GRUB_DEFAULT="numa_balancing=disable root=/dev/sda"
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=2
GRUB_CMDLINE_LINUX="quiet splash net.ifnames=1 biosdevname=0 ipv6.disable=1"
The task is idempotent.
Example of a complete playbook for testing
shell> cat pb.yml
- hosts: localhost
vars:
grub_file: /tmp/grub
grub_ini: "{{ out.stdout|community.general.jc('ini') }}"
grub_keys: "{{ grub_ini.keys()|list }}"
grub_vals: "{{ grub_ini.values()|map('split', ' ') }}"
grub_orig: "{{ dict(grub_keys|zip(grub_vals)) }}"
grub_update:
GRUB_DEFAULT:
- "numa_balancing=disable"
tasks:
- command:
cmd: "cat {{ grub_file }}"
register: out
- debug:
var: grub_orig
when: debug|d(false)|bool
- debug:
var: line
loop: "{{ grub_update.keys()|list }}"
vars:
line: "{{ (grub_update[item] + grub_orig[item|lower]|d([]))|
unique|
join(' ') }}"
when: debug|d(false)|bool
- lineinfile:
path: "{{ grub_file }}"
regexp: '^{{ item }}.*$'
line: '{{ item }}="{{ line }}"'
loop: "{{ grub_update.keys()|list }}"
vars:
line: "{{ (grub_update[item] + grub_orig[item|lower]|d([]))|
unique|
join(' ') }}"
gives
shell> ansible-playbook pb.yml -e debug=true --diff
PLAY [localhost] *****************************************************************************
TASK [command] *******************************************************************************
changed: [localhost]
TASK [debug] *********************************************************************************
ok: [localhost] =>
grub_orig:
grub_cmdline_linux:
- quiet
- splash
- net.ifnames=1
- biosdevname=0
- ipv6.disable=1
grub_default:
- root=/dev/sda
grub_timeout:
- '2'
grub_timeout_style:
- hidden
TASK [debug] *********************************************************************************
ok: [localhost] => (item=GRUB_DEFAULT) =>
ansible_loop_var: item
item: GRUB_DEFAULT
line: numa_balancing=disable root=/dev/sda
TASK [lineinfile] ****************************************************************************
--- before: /tmp/grub (content)
+++ after: /tmp/grub (content)
@@ -1,4 +1,4 @@
-GRUB_DEFAULT="root=/dev/sda"
+GRUB_DEFAULT="numa_balancing=disable root=/dev/sda"
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=2
GRUB_CMDLINE_LINUX="quiet splash net.ifnames=1 biosdevname=0 ipv6.disable=1"
changed: [localhost] => (item=GRUB_DEFAULT)
PLAY RECAP ***********************************************************************************
localhost: ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
As mentioned within the comments, to change the configuration you could use an approach like
- name: Set grub default in /etc/sysconfig/grub
replace:
path: "/etc/sysconfig/grub"
regexp: 'GRUB_DEFAULT="root=/dev/sda"'
replace: 'GRUB_DEFAULT="numa_balancing=disable root=/dev/sda"'
backup: true
Please take note that to reflect the change some more steps and a reboot may be necessary.
- name: Rebuild boot image to reflect the change
shell:
cmd: grub2-mkconfig -o /boot/efi/EFI/{{ DISTRIBUTION }}/grub.cfg
register: grub2_mkconfig
- debug:
msg: "{{ grub2_mkconfig.stderr_lines }}"
when: not ansible_check_mode
Further Q&A
which shows the usage of Ansible for GRUB bootloader configuration.