如何在Ansible后续任务中仅提取register输出中的SUCCESSFUL值?
问题
想在Ansible后续任务里提取第一个任务register输出中的SUCCESSFUL字符串,但执行时出现错误,结果不符合预期。
原Playbook内容:
cat play1.yml --- - hosts: all connection: local gather_facts: false tasks: - name: Parse result info shell: | cmd: | echo "Result output goes here. Some Exception number details : Exception from HRESULT" | grep "Exception from HRESULT" excep_status=`echo $?` if (( $excep_status == 0)) ; then echo "SUCCESSFUL" # Exception present elif (( $excep_status == 1)) ; then echo "FAILED" fi register: ExcepStatus delegate_to: localhost - debug: msg="{{ExcepStatus.stdout}}" - name: echo ExcepStatus shell: | echo {{ ExcepStatus.stdout }} delegate_to: localhost
清单文件:
$ cat inv localhost
执行报错结果:
$ ansible-playbook -i inv play1.yml PLAY [all] ************************************************************************************************************************************************** TASK [Parse result info] ************************************************************************************************************************************ changed: [localhost -> localhost] TASK [debug] ************************************************************************************************************************************************ ok: [localhost] => { "msg": "Result output goes here. Some Exception number details : Exception from HRESULT\nSUCCESSFUL" } TASK [echo ExcepStatus] ************************************************************************************************************************************* fatal: [localhost -> localhost]: FAILED! => {"changed": true, "cmd": "echo Result output goes here. Some Exception number details : Exception from HRESULT\nSUCCESSFUL\n", "delta": "0:00:00.011982", "end": "2023-12-18 05:00:49.203555", "msg": "non-zero return code", "rc": 127, "start": "2023-12-18 05:00:49.191573", "stderr": "/bin/sh: line 1: SUCCESSFUL: command not found", "stderr_lines": ["/bin/sh: line 1: SUCCESSFUL: command not found"], "stdout": "Result output goes here. Some Exception number details : Exception from HRESULT", "stdout_lines": ["Result output goes here. Some Exception number details : Exception from HRESULT"]} PLAY RECAP ************************************************************************************************************************************************** localhost : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
原因分析
第一个任务的stdout包含两行内容:第一行是grep的输出,第二行是状态值SUCCESSFUL。直接在shell任务中使用echo {{ ExcepStatus.stdout }}时,换行符会被shell解析成命令分隔符,导致第二行的SUCCESSFUL被当成独立命令执行,从而触发报错。
解决方法
有两种方式可以提取目标字符串:
方式1:利用stdout_lines取最后一行
Ansible会自动将stdout按行拆分成列表stdout_lines,状态值在最后一行,直接取列表的最后一个元素即可:
- name: echo ExcepStatus shell: | echo "{{ ExcepStatus.stdout_lines[-1] }}" delegate_to: localhost
方式2:用正则提取状态字符串
通过regex_search过滤出SUCCESSFUL或FAILED:
- name: echo ExcepStatus shell: | echo "{{ ExcepStatus.stdout | regex_search('SUCCESSFUL|FAILED') }}" delegate_to: localhost
额外优化:让第一个任务只输出状态
如果不需要保留grep的输出,可以直接修改第一个任务,让它只输出最终状态,这样后续直接用{{ ExcepStatus.stdout }}就不会有问题:
- name: Parse result info shell: | echo "Result output goes here. Some Exception number details : Exception from HRESULT" | grep -q "Exception from HRESULT" if (( $? == 0)) ; then echo "SUCCESSFUL" else echo "FAILED" fi register: ExcepStatus delegate_to: localhost
这里用grep -q让grep不输出匹配内容,只返回退出码,这样第一个任务的stdout就只有状态值,后续任务直接使用{{ ExcepStatus.stdout }}即可。
内容的提问来源于stack exchange,提问作者vinWin
相关产品推荐
相关产品推荐

