【问题标题】:How to use jq in ansible shell tasks如何在 ansible shell 任务中使用 jq
【发布时间】:2020-09-24 11:30:52
【问题描述】:

我正在尝试在 ansible playbook 中使用 jq 命令,但在运行 shell 命令时遇到问题

---
- name: shell
  hosts: localhost
  gather_facts: False
  vars:
    hbawwn_statement: '{ "HBA WWN" : "Pass" , "Result" : "a\nb" }'
    arrayno_statement: '{ "Storage Array Number" : "Pass" , "Result" : "0001a\n0001b" }'
    adapterslot_statement: '{ "Host Adapter Slot" : "Pass" , "Result" : "PCI Slot 3\nPCI Slot 2" }'
    adaptertype_statement: '{ "Host Adapter Type" : "Pass" , "Result" : "AJB/AHA\nAJB/AHA" }'


  tasks:
    - name: test
      set_fact:
        sk_out: "[{{ adaptertype_statement }}, {{ adapterslot_statement }}, {{ arrayno_statement }}, {{ hbawwn_statement }}]"
    - debug:
        msg: "{{ sk_out }}"
    - name: jq command
      shell: {{ sk_out }} | jq 'map_values(.Result | split("\n")) | transpose | map( {"Host Adapter Type":.[0], "Host Adapter Slot":.[1], "Storage Array Number":.[2],"HBA WWN":.[3]})' | jq -n '."CUT Sheet " |= [inputs]'
      register: out
    - debug:
        msg: "{{ out.stdout }}"

出现错误
错误!加载 YAML 时出现语法错误。
需要注释或换行符,但找到了 'j'\

错误似乎在“test_jq.yml”中:第 22 行第 29 列,但可能 根据确切的语法问题,位于文件的其他位置。

违规行似乎是:

- name: jq command
  shell: {{ sk_out }} | jq 'map_values(.Result | split("\n")) | transpose | map( {"Host Adapter Type":.[0], "Host Adapter Slot":.[1], "Storage Array Number":.[2],"HBA WWN":.[3]})' | jq -n '."CUT Sheet " |= [inputs]'
                        ^ here

我们可能错了,但这个看起来可能是一个问题 缺少引号。总是引用模板表达式括号 开始一个值。例如:

TASK [debug] 
ok: [localhost] => {
    "msg": [
        {
            "Host Adapter Type": "Pass", 
            "Result": "AJB/AHA\nAJB/AHA"
        }, 
        {
            "Host Adapter Slot": "Pass", 
            "Result": "PCI Slot 3\nPCI Slot 2"
        }, 
        {
            "Result": "0001a\n0001b", 
            "Storage Array Number": "Pass"
        }, 
        {
            "HBA WWN": "Pass", 
            "Result": "a\nb"
        }
    ]
}

已验证将 {{ sk_out }} 的内容复制到 txt 文件中
s.txt

[
        {
            "Host Adapter Type": "Pass", 
            "Result": "AJB/AHA\nAJB/AHA"
        }, 
        {
            "Host Adapter Slot": "Pass", 
            "Result": "PCI Slot 3\nPCI Slot 2"
        }, 
        {
            "Result": "0001a\n0001b", 
            "Storage Array Number": "Pass"
        }, 
        {
            "HBA WWN": "Pass", 
            "Result": "a\nb"
        }
    ]

输出

cat s.txt | jq 'map_values(.Result | split("\n")) | transpose | map( {"Host Adapter Type":.[0], "Host Adapter Slot":.[1], "Storage Array Number":.[2],"HBA WWN":.[3]})' | jq -n '."CUT Sheet " |= [inputs]'\

此命令有效
试图添加括号,如 shell: "{{ sk_out }}" | jq 但这是不工作的语法错误。
如何在不创建 txt 文件的情况下在 ansible playbook 中处理这个问题。

【问题讨论】:

  • 引用整个命令(并相应地转义引号),而不仅仅是开始时的 jinja2 表达式。另请注意,如果您只是输出您的 var(即未找到命令)而不是使用例如,bash 将出错。 echo 将其传递给管道中的下一个 jq。
  • 或者利用 jq 使用args: stdin: "{{ sk_out }}"从标准输入读取的事实

标签: ansible


【解决方案1】:

虽然 zeitounator 和 mdaniel 对该问题的评估非常正确,但我建议使用 > YAML 构造,而不是在已经包含引号的表达式周围再添加一对引号:

...
    - name: jq command
      shell: >
        echo "{{ sk_out }}"
        | jq 'map_values(.Result | split("\n")) | transpose | map( {"Host Adapter Type":.[0], "Host Adapter Slot":.[1], "Storage Array Number":.[2],"HBA WWN":.[3]})'
        | jq -n '."CUT Sheet " |= [inputs]'
      register: out
...

我相信这会让您的代码更易于阅读和维护。

也就是说,这个字典(或映射,或哈希表,或关联数组,无论你怎么称呼它)都可以在 ansible 本身内部执行,不需要去shell+jq。看看 Ansible 过滤器:

https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html

还有 Jinja2(模板引擎)内置过滤器:

https://jinja.palletsprojects.com/en/2.11.x/templates/#list-of-builtin-filters

HTH

亚历克斯

【讨论】:

  • 这个 yaml 结构终于让我的代码真正可读了。谢谢!
【解决方案2】:

我不确定你到底想做什么,但作为一个可能已经完成你想要的事情的例子,你可以:

  - set_fact:
      stmt_keys: "{{ stmt_keys|d([]) + [(item|list|reject('equalto', 'Result')|list)[0]] }}"
      stmt_results: "{{ stmt_results|d([]) + [item['Result'].split('\n')] }}"
    loop: "{{ sk_out }}"

  - set_fact:
      alt_out: "{{ stmt_keys | zip(stmt_results) | list }}"

  - name: non-jq command
    debug:
      msg: alternate={{ item }}
    loop: "{{ alt_out }}"

生成输出:

...

TASK [non-jq command] *****************************************************************************
ok: [localhost] => (item=['Host Adapter Type', ['AJB/AHA', 'AJB/AHA']]) => {
    "msg": "alternate=['Host Adapter Type', ['AJB/AHA', 'AJB/AHA']]"
}
ok: [localhost] => (item=['Host Adapter Slot', ['PCI Slot 3', 'PCI Slot 2']]) => {
    "msg": "alternate=['Host Adapter Slot', ['PCI Slot 3', 'PCI Slot 2']]"
}
ok: [localhost] => (item=['Storage Array Number', ['0001a', '0001b']]) => {
    "msg": "alternate=['Storage Array Number', ['0001a', '0001b']]"
}
ok: [localhost] => (item=['HBA WWN', ['a', 'b']]) => {
    "msg": "alternate=['HBA WWN', ['a', 'b']]"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    相关资源
    最近更新 更多