问题描述
希望解决一个问题:他想在/boot/grub/grub.conf
文件中的所有内核定义中添加设置pci=noaer
,但只有在该设置不存在时才添加。他已经成功地使用replace
模块实现了基本功能,即模块会将设置添加到相关行,但问题在于在已存在该设置的行上不进行添加。换句话说,如果他运行一次Playbook,它会根据需要添加设置,但在此之后的每次Playbook运行都会将该设置的另一个实例添加到每行中。以下是他想要更新的行的示例以及他目前配置的正则表达式和替换行:
Line to change:
kernel /vmlinuz-2.6.32-279.22.1.el6.x86_64 ro root=/dev/sda3
After the playbook runs the above line should look like:
kernel /vmlinuz-2.6.32-279.22.1.el6.x86_64 ro root=/dev/sda3 pci=noaer
Relevant replace module parameters:
regexp: '(^\s+kernel /vmlinuz.+(?!pci=noaer).*$)'
replace: '\1 pci=noaer'
用户尝试使用\b
序列来明确定义pci=noaer
的边界(例如(?!\bpci=noaer\b)
),但没有成功。他在regex101上进行了一些测试,但实际上并不能确定为什么负向前瞻不像预期那样工作(寻找不包含pci=noaer
字符串的情况),或者他在替换模块中如何使用它。他还提到,在lineinfile
中使用负向前瞻/负向后瞻也存在类似的问题。鉴于他对Ansible和Python相对较新,并且对正则表达式的技能有限,他承认这可能完全是用户错误。他还指出,他搜索了很多资料,但似乎找不到负向前瞻在这些模块中不按预期工作的原因。
此外,他还提到,有些2.x版本的Ansible中可能存在关于前瞻/后瞻的问题,所以这可能是版本问题。他使用的是Ansible 2.6.20和底层Python版本为2.6.6。如果确实是版本问题,是否有其他方法可以避免更新到更近的版本而解决这个问题?
还有一点补充信息:这在多个基于CentOS 6的系统上进行,他不能保证grub.conf
文件中的内核行在不同系统之间是相同的(也许应该是相同的,但这是一个不同讨论的话题)。这就是为什么他使用了相对非特定的正则表达式。另外,由于这是CentOS 6,所以没有类似于update-grub
或grub2-mkconfig
的等效工具。只需要编辑/etc/grub.conf
或/boot/grub/grub.conf
文件并重新启动即可。
解决方案
请注意以下操作注意版本差异及修改前做好备份。
使用正则表达式替换模块
你可以尝试使用正则表达式替换模块来达到在行中添加缺失字符串的目的。在你的regexp
表达式中,由于你的内核行可能具有不同的前缀空格数,你应该使用\s*
来匹配不确定数量的空格。此外,你可以使用负向前瞻断言来排除已经包含了pci=noaer
的行。以下是一个示例配置:
- name: Add pci=noaer to kernel lines
replace:
path: /boot/grub/grub.conf
regexp: '^(?!.*\bpci=noaer\b)(\s*kernel /vmlinuz.*)$'
replace: '\1 pci=noaer'
在上面的配置中,regexp
表达式会匹配以kernel /vmlinuz
开头的行,但排除了已包含pci=noaer
的行。然后,replace
表达式使用捕获组和回溯引用来将已有的行内容保留,并在其后添加pci=noaer
。
如果你的版本问题确实导致问题,这种方法应该在你的版本中有效。不过,如果问题仍然存在,你可以尝试其他方法。
使用命令行处理
如果以上方法仍然无法解决问题,你可以考虑使用命令行来处理此操作。你可以编写一个自定义的bash脚本,以及一些命令行工具,以便在特定条件下修改grub.conf
文件。以下是一个示例bash脚本,用于处理这个问题:
#!/bin/bash
# 备份原始文件
cp /boot/grub/grub.conf /boot/grub/grub.conf.bak
# 遍历文件中的每一行
while IFS= read -r line; do
# 检查行是否已包含 pci=noaer
if [[ "$line" != *"pci=noaer"* ]]; then
# 添加 pci=noaer 到行尾
echo "$line pci=noaer" >> /boot/grub/grub.conf.tmp
else
# 直接写入行到临时文件
echo "$line" >> /boot/grub/grub.conf.tmp
fi
done < /boot/grub/grub.conf
# 将临时文件替换为原始文件
mv /boot/grub/grub.conf.tmp /boot/grub/grub.conf
# 重启系统以使更改生效
reboot
请注意,以上脚本假设你有足够的权限来修改/boot/grub/grub.conf
文件并重新启动系统。运行