如何用简洁命令注释Ansible Vault加密变量及其后续缩进内容?
问题描述
我正在编写Ansible Playbook,用于自动存储由Play生成的Ansible Vault加密密钥,密钥在YAML文件中的格式如下:
--- my_secret_thing: !vault | $ANSIBLE_VAULT;1.1;AES256 64356439663234656438636635316531623966623736396235376562613039356435623135366164 3939626637326538663934636637643761etcetcetc
当密钥变更时,我需要注释掉整个旧密钥并添加新密钥。最初我用以下Ansible任务来注释旧密钥:
- name: Comment out previous secret run_once: True ansible.builtin.shell: "grep '^my_secret_thing' $PWD/{{ env }}_group_vars/secrets.yml && START=$(cat $PWD/{{ env }}_group_vars/secrets.yml |grep -n '^my_secret_thing'|cut -d ':' -f 1) && END=$(expr $START + 10) && sed -i \"$START,$END s/^/#/\" $PWD/{{ env }}_group_vars/secrets.yml" delegate_to: 127.0.0.1 ignore_errors: True # Otherwise will 'fail' if no token is currently stored
一开始我假设每个密钥占用固定10行,但实际情况并非如此。所以我想替换这个Shell命令,实现匹配my_secret_thing:这一行,然后注释该行以及所有后续以10个空格开头的行,直到遇到下一个无缩进的变量行(行首无空格)。我自己写了一段bash脚本,但希望能用更简洁的单行命令实现,请问有什么建议?
附我编写的bash脚本:
#!/bin/bash MATCH=0 COUNT=0 IFS=$'\n' for LINE in `cat secrets.yml`; do if [ $MATCH -eq 0 ]; then if [ `echo $LINE |grep '^my_secret_stuff:'` ]; then MATCH=1 continue else continue fi fi if [ $MATCH -eq 1 ]; then if [ $MATCH -eq 1 ] && [ `echo $LINE |grep '^ \{10\}'` ]; then let COUNT++ continue elif [ `echo $LINE |grep '^[a-z_]*:'` ]; then break fi fi done unset IFS echo $COUNT
解决方案
可以用sed或awk的多行匹配功能实现需求,替代复杂的循环脚本,以下是两种简洁的单行命令方案:
方案1:使用sed命令
sed -i '/^my_secret_thing:/,/^[^ ]/ {/^my_secret_thing:/s/^/#/; /^ /s/^/#/}' $PWD/{{ env }}_group_vars/secrets.yml
命令说明:
/^my_secret_thing:/,/^[^ ]/:定义匹配范围,从my_secret_thing:开头的行开始,直到遇到行首非空格的行结束。{/^my_secret_thing:/s/^/#/; /^ /s/^/#/}:在范围内执行两个替换操作:- 给
my_secret_thing:开头的行首添加#注释 - 给以10个空格开头的密钥内容行首添加
#注释
- 给
注:如果是macOS环境的BSD sed,需要在-i后加空参数,命令调整为:
sed -i '' '/^my_secret_thing:/,/^[^ ]/ {/^my_secret_thing:/s/^/#/; /^ /s/^/#/}' $PWD/{{ env }}_group_vars/secrets.yml
方案2:使用awk命令(逻辑更清晰)
awk '/^my_secret_thing:/ {flag=1} flag {sub(/^/,"#")} /^[^ ]/ && flag {flag=0} 1' $PWD/{{ env }}_group_vars/secrets.yml > temp.yml && mv temp.yml $PWD/{{ env }}_group_vars/secrets.yml
命令说明:
/^my_secret_thing:/ {flag=1}:匹配到目标变量行时,开启标记flagflag {sub(/^/,"#")}:标记开启时,给当前行首添加#注释/^[^ ]/ && flag {flag=0}:遇到行首非空格的行且标记开启时,关闭标记1:打印所有行(包括注释后的行)
将awk命令替换到Ansible任务中:
- name: Comment out previous secret run_once: True ansible.builtin.shell: | awk '/^my_secret_thing:/ {flag=1} flag {sub(/^/,"#")} /^[^ ]/ && flag {flag=0} 1' $PWD/{{ env }}_group_vars/secrets.yml > temp.yml && mv temp.yml $PWD/{{ env }}_group_vars/secrets.yml delegate_to: 127.0.0.1 ignore_errors: True
内容的提问来源于stack exchange,提问作者anfieldroad
相关产品推荐
相关产品推荐

