美文网首页
使用json_query过滤输出内容

使用json_query过滤输出内容

作者: super_pcm | 来源:发表于2021-03-26 18:36 被阅读0次

我们都知道在使用ansible的shell模块执行命令或者运行脚本的时候是没有返回信息的,为了能够打印出执行的结果我们通常使用register来注册变量,然后使用debug模块来输出结果,如下:

---
- hosts: localhost
  gather_facts: false
  tasks:
  - name: test shell
    shell: "echo 112"
    register: info

  - debug: msg="{{ info }}"

上面playbook执行的结果如下所示:

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [test shell] ***************************************************************************************************************************************************************************
changed: [localhost]

TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": {
        "changed": true, 
        "cmd": "echo 112", 
        "delta": "0:00:00.309961", 
        "end": "2021-03-26 18:04:47.401284", 
        "failed": false, 
        "rc": 0, 
        "start": "2021-03-26 18:04:47.091323", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "112", 
        "stdout_lines": [
            "112"
        ]
    }
}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

为了简化输出,我们可以只输出stdout_lines部分,如下

---
...
  - debug: msg="{{ info.stdout_lines }}"

上面的playbook只输出标准输出部分

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [test shell] ***************************************************************************************************************************************************************************
changed: [localhost]

TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "112"
    ]
}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

这种场景下的输出问题不大,现在有个需求,我要执行很多的shell语句,通常我们会使用列表的方式书写playbook,如下:

---
- hosts: localhost
  gather_facts: false
  tasks:
  - name: test shell
    shell: "echo {{ item }}"
    with_items:
      - '123'
      - '456'
      - '789'
    register: info

  - debug: msg="{{ info.stdout_lines }}"

这时候我们希望获取stdout_lines部分的输出,看下能不能获取到:

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [test shell] ***************************************************************************************************************************************************************************
changed: [localhost] => (item=123)
changed: [localhost] => (item=456)
changed: [localhost] => (item=789)

TASK [debug] ********************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout_lines'\n\nThe error appears to be in '/opt/everhomes-ansible/test.yml': line 13, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n  - debug: msg=\"{{ info.stdout_lines }}\"\n    ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n    with_items:\n      - {{ foo }}\n\nShould be written as:\n\n    with_items:\n      - \"{{ foo }}\"\n"}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

发现报错了,提示字典对象里面没有stdout_lines这个key。我们改下playbook,看下输出所有的结果。

---
...
  - debug: msg="{{ info }}"

输出结果很长

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [test shell] ***************************************************************************************************************************************************************************
changed: [localhost] => (item=123)
changed: [localhost] => (item=456)
changed: [localhost] => (item=789)

TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": {
        "changed": true, 
        "msg": "All items completed", 
        "results": [
            {
                "ansible_loop_var": "item", 
                "changed": true, 
                "cmd": "echo 123", 
                "delta": "0:00:00.285530", 
                "end": "2021-03-26 18:17:11.955852", 
                "failed": false, 
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo 123", 
                        "_uses_shell": true, 
                        "argv": null, 
                        "chdir": null, 
                        "creates": null, 
                        "executable": null, 
                        "removes": null, 
                        "stdin": null, 
                        "stdin_add_newline": true, 
                        "strip_empty_ends": true, 
                        "warn": true
                    }
                }, 
                "item": "123", 
                "rc": 0, 
                "start": "2021-03-26 18:17:11.670322", 
                "stderr": "", 
                "stderr_lines": [], 
                "stdout": "123", 
                "stdout_lines": [
                    "123"
                ]
            }, 
            {
                "ansible_loop_var": "item", 
                "changed": true, 
                "cmd": "echo 456", 
                "delta": "0:00:00.287871", 
                "end": "2021-03-26 18:17:12.403742", 
                "failed": false, 
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo 456", 
                        "_uses_shell": true, 
                        "argv": null, 
                        "chdir": null, 
                        "creates": null, 
                        "executable": null, 
                        "removes": null, 
                        "stdin": null, 
                        "stdin_add_newline": true, 
                        "strip_empty_ends": true, 
                        "warn": true
                    }
                }, 
                "item": "456", 
                "rc": 0, 
                "start": "2021-03-26 18:17:12.115871", 
                "stderr": "", 
                "stderr_lines": [], 
                "stdout": "456", 
                "stdout_lines": [
                    "456"
                ]
            }, 
            {
                "ansible_loop_var": "item", 
                "changed": true, 
                "cmd": "echo 789", 
                "delta": "0:00:00.287773", 
                "end": "2021-03-26 18:17:12.846252", 
                "failed": false, 
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo 789", 
                        "_uses_shell": true, 
                        "argv": null, 
                        "chdir": null, 
                        "creates": null, 
                        "executable": null, 
                        "removes": null, 
                        "stdin": null, 
                        "stdin_add_newline": true, 
                        "strip_empty_ends": true, 
                        "warn": true
                    }
                }, 
                "item": "789", 
                "rc": 0, 
                "start": "2021-03-26 18:17:12.558479", 
                "stderr": "", 
                "stderr_lines": [], 
                "stdout": "789", 
                "stdout_lines": [
                    "789"
                ]
            }
        ]
    }
}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

可以看到输出结果很长,其中我们想要的内容在 info.results 这个列表里面。如果要获取到第一个stdout_lines的值我们可以这样来:

---
...
  - debug: msg="{{ info.results[0].stdout_lines }}"

可以得到我们想要的结果

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [test shell] ***************************************************************************************************************************************************************************
changed: [localhost] => (item=123)
changed: [localhost] => (item=456)
changed: [localhost] => (item=789)

TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "123"
    ]
}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

因为info.results是一个列表,也就是说我们可以使用 with_items的方式来循环输出所有我们想要的结果

---
...
  - debug: msg="{{ item.stdout_lines }}" 
    with_items: "{{ info.results }}"

得到的输出结果

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [test shell] ***************************************************************************************************************************************************************************
changed: [localhost] => (item=123)
changed: [localhost] => (item=456)
changed: [localhost] => (item=789)

TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => (item={u'stderr_lines': [], u'ansible_loop_var': u'item', u'end': u'2021-03-26 18:25:08.107230', u'stdout': u'123', u'item': u'123', u'changed': True, u'rc': 0, u'failed': False, u'cmd': u'echo 123', u'stderr': u'', u'delta': u'0:00:00.279638', u'invocation': {u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': True, u'strip_empty_ends': True, u'_raw_params': u'echo 123', u'removes': None, u'argv': None, u'warn': True, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}, u'stdout_lines': [u'123'], u'start': u'2021-03-26 18:25:07.827592'}) => {
    "msg": [
        "123"
    ]
}
ok: [localhost] => (item={u'stderr_lines': [], u'ansible_loop_var': u'item', u'end': u'2021-03-26 18:25:08.548255', u'stdout': u'456', u'item': u'456', u'changed': True, u'rc': 0, u'failed': False, u'cmd': u'echo 456', u'stderr': u'', u'delta': u'0:00:00.280673', u'invocation': {u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': True, u'strip_empty_ends': True, u'_raw_params': u'echo 456', u'removes': None, u'argv': None, u'warn': True, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}, u'stdout_lines': [u'456'], u'start': u'2021-03-26 18:25:08.267582'}) => {
    "msg": [
        "456"
    ]
}
ok: [localhost] => (item={u'stderr_lines': [], u'ansible_loop_var': u'item', u'end': u'2021-03-26 18:25:08.980572', u'stdout': u'789', u'item': u'789', u'changed': True, u'rc': 0, u'failed': False, u'cmd': u'echo 789', u'stderr': u'', u'delta': u'0:00:00.281573', u'invocation': {u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': True, u'strip_empty_ends': True, u'_raw_params': u'echo 789', u'removes': None, u'argv': None, u'warn': True, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}, u'stdout_lines': [u'789'], u'start': u'2021-03-26 18:25:08.698999'}) => {
    "msg": [
        "789"
    ]
}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

可以看到我们除了得到我们想要的结果之外,还有很多我们不想看到的内容。比如,ansible会给我们加上每个item的内容。到这里,问题似乎无解了。除非修改ansible的配置,让它不显示item的内容,但是这样肯定会影响我们日常使用ansible。无解了。


不华丽的分割线


百度了好久,终于找到了json_query过滤器。通过json_query我们可以完成我们的目标。

---
...
  - debug: msg="{{ info.results |json_query('[].stdout_lines []') }}"

终于得到我想要的结果了.

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [test shell] ***************************************************************************************************************************************************************************
changed: [localhost] => (item=123)
changed: [localhost] => (item=456)
changed: [localhost] => (item=789)

TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "123", 
        "456", 
        "789"
    ]
}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

好了,问题解决了.找时间深入学习下ansible才行,还有好多过滤器.

相关文章

  • 使用json_query过滤输出内容

    我们都知道在使用ansible的shell模块执行命令或者运行脚本的时候是没有返回信息的,为了能够打印出执行的结果...

  • 过滤器

    过滤器是一个使用在 双大括号插值 和 v-bind 中,用于过滤输出内容的函数 假设有一个用于把内容转为大写的过滤...

  • 【Linux命令行与shell脚本编程大全】3 基本的 bash

    3.5.3.1 ls 命令使用元字符通配符过滤输出列表 ls 命令使用通配符过滤输出列表,被称为 文件扩展匹配( ...

  • 安卓开发-logcat使用

    使用 adb logcat命令行结合grep很方面的过滤想要的内容并输出到文件中 adb logcat | gre...

  • android studio 日志过滤

    使用Regex过滤器过滤logcat的输出: 添加你要隐藏的任何其他标签:

  • Django-07 模板层 过滤器和继承

    模板过滤器 定义:在变量输出时对变量的值进行处理 作用:可以通过使用过滤器来改变变量的输出显示 语法:{{ 变量 ...

  • 查看和终止Unix进程

    要点: $ ps aux查看系统所有进程 $ ps aux | grep 使用grep过滤输出 $ ...

  • velocity语法需要注意的!

    输出过滤 ${}过滤输出 输出表达式的计算结果,并根据所处HTML的位置智能进行过滤,比如:过滤变量中的HTML标...

  • 在小密圈里创建收费知识社群

    知识有价。 收费圈子的好处,至少有: 建立门槛,过滤掉观光客; 逼自己尽可能多地思考和输出内容; 通过输出内容,和...

  • 输出函数和输入函数

    输出函数 1.在C语言中, 我们使用printf来输出内容2.在Go语言中也可以使用printf输出内容, 但是在...

网友评论

      本文标题:使用json_query过滤输出内容

      本文链接:https://www.haomeiwen.com/subject/pmcshltx.html