As Vladimir pointed out, Jack's answer unfortunately is not sufficient for empty files and also fails if the desired argument already exists at the beginning of the line.
The following suggested solution should address those issues. In particular, it is supposed to
- support empty files,
- support existing arguments at any position within the string,
- be robust even with multi-line files (just in case...),
- be idempotent, and
- optionally update existing keys with the desired value.
Original version May 2021:
# cmdline.yml
- name: read cmdline.txt
become: true
slurp: "src={{ cmdline_txt_path }}"
register: result_cmdline
- name: generate regular expression for existing arguments
set_fact:
regex_existing: '{{ "\b" + key|string + "=" + ("[\w]*" if update else value|string) + "\b" }}'
key_value_pair: '{{ key|string + "=" + value|string }}'
- name: generate regular expression for new arguments
set_fact:
regex_add_missing: '{{ "^((?!(?:.|\n)*" + regex_existing + ")((?:.|\n)*))$" }}'
- name: update cmdline.txt
become: true
copy:
content: '{{ result_cmdline.content
| b64decode
| regex_replace(regex_existing, key_value_pair)
| regex_replace(regex_add_missing, key_value_pair + " \1")
}}'
dest: "{{ cmdline_txt_path }}"
Updated version August 2023:
Adds support for keys without values and allows removing keys.
# cmdline.yml
- name: read cmdline.txt
slurp: "src={{ cmdline_txt_path }}"
register: result_cmdline
- name: generate regular expression for existing arguments
set_fact:
regex_existing: '{{ "\b" + key|string + "(?:=" + ("[\w]*" if update|default(true) else value|string) + ")?(?![\w=])" }}'
key_value_pair: '{{ "" if remove|default(false) else ("" + key|string + (("=" + value|string) if value is defined else "")) }}'
- name: generate regular expression for new arguments
set_fact:
regex_add_missing: '{{ "^((?!(?:.|\n)*" + regex_existing + ")((?:.|\n)*))$" }}'
- name: update cmdline.txt
copy:
content: '{{ result_cmdline.content
| b64decode
| regex_replace(regex_existing, key_value_pair)
| regex_replace(regex_add_missing, key_value_pair + ("\1" if remove|default(false) else " \1"))
| regex_replace("\s+", " ") | trim # in case you don't like extra whitespaces
}}'
dest: "{{ cmdline_txt_path }}"
Usage:
- set_fact:
cmdline_txt_path: /boot/cmdline.txt
- include_tasks: cmdline.yml
vars:
key: cgroup_enable
value: memory
update: false
# will add the argument if the key-value-pair doesn't exist
- include_tasks: cmdline.yml
vars:
key: cgroup_enable
value: cpu
update: false
- include_tasks: cmdline.yml
vars:
key: cgroup_memory
value: 1
update: true
# will replace the value of the first matching key, if found;
# will add it if it's not found
# The following examples need the updated version from August 2023:
- include_tasks: cmdline.yml
vars:
key: quiet
# will add key without "=" and without value if not present
- include_tasks: cmdline.yml
vars:
key: quiet
remove: true
# will remove all matching keys
I didn't have a lot of time to test the updated version. Feel free to try it out and give feedback. Thanks!