首页 > 解决方案 > 在ansible中,如何打印任务失败的每个项目的标准错误?

问题描述

我有一组由用户输入提供的服务器,我想测试列表中的每个服务器,如果有任何失败,我想知道哪些失败以及为什么失败(stderr)。注意,服务器的数量不会是一致的,所以解决方案需要动态地发送服务器的数量。

命令

ansible-playbook test.yml -e '{"chrony_servers":["0.centos.pool.ntp.org","10.centos.pool.ntp.org"]}'

测试.yml

- name: Services Playbook
  hosts: localhost
  tasks:

  - name: Install nmap-ncat
    yum: name=nc state=present

  - name: Validate chrony_servers
    command: nc -vzu {{ item }} 123
    with_items:
      - "{{ chrony_servers }}"
    ignore_errors: yes
    register: chrony_server_results

  - debug: var=chrony_server_results

  - fail:
      msg: "{{ chrony_server_results.results.stderr }}"
    when: chrony_server_results.failed is defined and chrony_server_results.failed == true

这是来自此示例的输出

TASK [debug] ********************************************************************************************************************************************************************
ok: [localhost] => {
    "chrony_server_results": {
        "changed": true,
        "failed": true,
        "msg": "All items completed",
        "results": [
            {
                "_ansible_ignore_errors": true,
                "_ansible_item_label": "0.centos.pool.ntp.org",
                "_ansible_item_result": true,
                "_ansible_no_log": false,
                "_ansible_parsed": true,
                "changed": true,
                "cmd": [
                    "nc",
                    "-vzu",
                    "0.centos.pool.ntp.org",
                    "123"
                ],
                "delta": "0:00:02.217171",
                "end": "2019-05-16 18:58:54.070600",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "nc -vzu 0.centos.pool.ntp.org 123",
                        "_uses_shell": false,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "warn": true
                    }
                },
                "item": "0.centos.pool.ntp.org",
                "rc": 0,
                "start": "2019-05-16 18:58:51.853429",
                "stderr": "Ncat: Version 7.50 ( https://nmap.org/ncat )\nNcat: Connected to 208.75.88.4:123.\nNcat: UDP packet sent successfully\nNcat: 1 bytes sent, 0 bytes received in 2.21 seconds.",
                "stderr_lines": [
                    "Ncat: Version 7.50 ( https://nmap.org/ncat )",
                    "Ncat: Connected to 208.75.88.4:123.",
                    "Ncat: UDP packet sent successfully",
                    "Ncat: 1 bytes sent, 0 bytes received in 2.21 seconds."
                ],
                "stdout": "",
                "stdout_lines": []
            },
            {
                "_ansible_item_label": "10.centos.pool.ntp.org",
                "_ansible_item_result": true,
                "_ansible_no_log": false,
                "_ansible_parsed": true,
                "changed": true,
                "cmd": [
                    "nc",
                    "-vzu",
                    "10.centos.pool.ntp.org",
                    "123"
                ],
                "delta": "0:00:00.312970",
                "end": "2019-05-16 18:58:54.510976",
                "failed": true,
                "invocation": {
                    "module_args": {
                        "_raw_params": "nc -vzu 10.centos.pool.ntp.org 123",
                        "_uses_shell": false,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "warn": true
                    }
                },
                "item": "10.centos.pool.ntp.org",
                "msg": "non-zero return code",
                "rc": 2,
                "start": "2019-05-16 18:58:54.198006",
                "stderr": "Ncat: Version 7.50 ( https://nmap.org/ncat )\nNcat: Could not resolve hostname \"10.centos.pool.ntp.org\": Name or service not known. QUITTING.",
                "stderr_lines": [
                    "Ncat: Version 7.50 ( https://nmap.org/ncat )",
                    "Ncat: Could not resolve hostname \"10.centos.pool.ntp.org\": Name or service not known. QUITTING."
                ],
                "stdout": "",
                "stdout_lines": []
            }
        ]
    }
}

TASK [fail] *********************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'stderr'\n\nThe error appears to have been in '/home/vera/test.yml': line 14, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  - debug: var=chrony_server_results\n  - fail:\n    ^ here\n"}
    to retry, use: --limit @/home/vera/test.retry

PLAY RECAP **********************************************************************************************************************************************************************

预期结果应该类似于

"stderr": "Ncat: Version 7.50 ( https://nmap.org/ncat )\nNcat: Could not resolve hostname \"10.centos.pool.ntp.org\": Name or service not known. QUITTING."

标签: ansible

解决方案


你的结构chrony_server_results是一个字典,与你的调试任务假设的结构有点不同。
它在顶层有一些键,它们适用于您with_items作为一个整体调用的任务,例如changedfailed。各个调用的“子结果”包含各自的stderrrc属性,存储在具有键的数组中results
这意味着这chrony_server_results.results.stderr是错误的,并且该错误告诉您该数组没有stderr属性,而是单个条目有多个属性,您需要对其进行迭代。您可以检查rc以了解相应的调用是否实际失败(因为 netcat 显然在所有情况下都会写入 stderr)。

rc以下解决方案首先构建一个仅包含大于零的结果的数组,然后仅显示这些结果的调试消息:

 - set_fact:
     failed_results: "{{ chrony_server_results.results | selectattr('rc', '>', 0) | list }}"

 - name: Show the stderrs of failed_results
   debug:
     msg: "{{ item.stderr }}"
   with_items: "{{ failed_results }}"

  - fail:
      msg: "See debug output above"
    when: failed_results | length > 0

第一个表达式中使用的过滤器是 jinja2 的一部分,并在此处记录:http: //jinja.pocoo.org/docs/2.10/templates/#selectattr


推荐阅读