我正在学习ansible,无法用asnible简单地解决这个问题。
我有一个文件,其中包含:
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc cgroup_memory=1 cgroup_enable=memory
这是一行,例如,我想检查cgroup_memory是否设置为1,如果没有设置为1以及是否缺少整个设置,请将其追加到行的末尾。
我知道如何用bash和sed做这件事的非常简单的方法,但我无法理解ansible";正确的";方法,不使用线内野和替换整个线。。。如前所述,lineinfile正在使用整条线,所以我认为这并不理想。。我研究的下一个模块是可能工作的替换,但我不能只寻找";cgroup_memory=1";正如它所看到的";cgroup_memory=0";并被评价为不是";cgroup_memory=1";最后我在一个文件中得到了cgroup_memory=1 cgroup_mediary=0。。。不知何故,我需要提取值,比较并替换值(保持整行完整(,如果不存在,则附加到行的末尾。。。
以下是我想要的ansible中的bash版本:https://pastebin.com/1TCz30Nq
这是我最接近我需要的东西:
- name: "Check for cgroup_memory"
shell: grep -v '^[[:space:]]*#' /tmp/cmdline.txt_old | grep -icP "cgroup_memory=-?d+[[:space:]]" || true
register: grep_value
changed_when: False
- debug:
var: grep_value
- name: "Variable Missing: Add cgroup_memory=1 to end of line"
become: true
replace: dest=/tmp/cmdline.txt_old regexp='(s+)$' replace=' cgroup_memory=1'
when: grep_value.stdout == "0"
- name: "Variable Exist: Set cgroup_memory=1"
become: true
replace: dest=/tmp/cmdline.txt_old regexp='cgroup_memory=d+' replace='cgroup_memory=1'
when: grep_value.stdout == "1"
然而,这并没有忽略#lines,所以替换会很高兴地更改注释中的值,这很糟糕。同样,这并没有评估价值,但我想我可以在确定它在那里后进一步拆分。。我不想抱怨,但ansible被宣传为非常适合配置管理,我通过shell脚本做的第一件简单的事情并没有那么简单。。。(如果我不想使用外壳模块(
确保cgroup_memory
设置为1的一种方法是使用Ansible替换模块。替换模块可以匹配regexp
,并将其替换为我们想要的。
示例:
tasks:
- name: set cgroup_memory to 1
replace:
path: /path/to/file
regexp: 'cgroup_memory=d+'
replace: 'cgroup_memory=1'
如果有多行具有此表达式,则将替换所有出现的行。我们可以在上述任务中使用before
或after
参数来针对特定的参数。
或者我们可以使用lineinfile模块来确保整条线都存在。
tasks:
- name: ensure line with cgroup_memory is present in file
lineinfile:
path: /path/to/file
regexp: 'cgroup_memory=d+'
line: "net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc cgroup_memory=1 cgroup_enable=memory"
最好的选项IMHO是blockinfile。给定下方的配置文件
shell> cat test.cfg
line1
line2
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc cgroup_memory=1 cgroup_enable=memory
line4
line5
先划线blockinfile需要标记来找到块(在这种情况下是一条线(。例如
- lineinfile:
path: test.cfg
insertbefore: "^net.ifnames(.*)$"
line: "# BEGIN ANSIBLE MANAGED BLOCK my_block_01"
- lineinfile:
path: test.cfg
insertafter: "^net.ifnames(.*)$"
line: "# END ANSIBLE MANAGED BLOCK my_block_01"
给出
shell> cat test.cfg
line1
line2
# BEGIN ANSIBLE MANAGED BLOCK my_block_01
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait=fixrtc cgroup_memory=1 cgroup_enable=memory
# END ANSIBLE MANAGED BLOCK my_block_01
line4
line5
上面的lineinfile任务是幂等的。然后使用配置创建一个变量。例如
shell> cat net_cfg.yml
net_cfg_01:
- {key: 'net.ifnames', val: 0}
- {key: 'dwc_otg.lpm_enable', val: 0}
- {key: 'console', val: 'serial0,115200'}
- {key: 'console', val: 'tty1'}
- {key: 'root', val: 'LABEL=writable'}
- {key: 'rootfstype', val: 'ext4'}
- {key: 'elevator', val: 'deadline'}
- {key: 'rootwait', val: 'fixrtc'}
- {key: 'cgroup_memory', val: 1}
- {key: 'cgroup_enable', val: 'memory'}
必须使用列表,而不是更简单的字典,因为键不是唯一的。创建模板。例如
shell> cat templates/net_cfg_01.j2
{% for i in net_cfg_01 %}{{i.key}}={{i.val}} {% endfor %}
现在,您可以在文件中包含变量并配置行
- include_vars: net_cfg.yml
- blockinfile:
path: test.cfg
block: "{{ lookup('template', 'net_cfg_01.j2') }}"
marker: "# {mark} ANSIBLE MANAGED BLOCK my_block_01"
钞票
- 根据您的需要和文件的注释格式调整标记
- 模板在行尾之前留下一个空白。如有必要,请使用loop.last进行修复
- 所有任务都是幂等的
如何使用它
关于如何使用上述框架,有很多选择。例如,将配置变量放入列表
shell> cat net_cfg.yml
net_cfg_01:
...
- {key: 'cgroup_memory', val: {{ my_cgroup_memory }}}
然后下面的命令将确保文件配置正确
shell> ansible-playbook playbook.yml -e 'my_cgroup_memory=1'