使用ansible进行调试:如何从失败的命令中获取stderr和stdout,以尊重换行符的方式打印出来,从而使其易于阅读?

sto*_*tic 6 ansible

如果我运行一个简单的ansible剧本,那么经常会从失败的任务中获得难以阅读的输出,如下所示。大问题:

  • 标准输出中的换行符打印为\ n,而不是实际的换行符。这使得诸如python追溯之类的东西非常令人讨厌。

  • stdout,stderr,cmd ...输出的json blob包含很多有用的东西,但是由于它们都在同一行上一起运行,因此人类很难解析。

我怎样才能以一种易于阅读的格式打印其输出,以便进行调试?

这是令人讨厌的输出:

$ ansible-playbook playbooks/backUpWebsite.yml

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

TASK [command] 
*****************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "python -c 'ksjfasdlkjf'", "delta": "0:00:00.037459", "end": "2017-10-03 19:58:50.525257", "failed": true, "rc": 1, "start": "2017-10-03 19:58:50.487798", "stderr": "Traceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nNameError: name 'ksjfasdlkjf' is not defined", "stdout": "", "stdout_lines": [], "warnings": []}
        to retry, use: --limit @<snip>playbooks/backUpWebsite.retry

PLAY RECAP 
*********************************************************************
localhost                  : ok=0    changed=0    unreachable=0 failed=1   
Run Code Online (Sandbox Code Playgroud)

这是生成它的脚本:

---
- hosts: localhost
  gather_facts: False
  tasks:
      #wrong on purpose!
    - shell: "python -c 'ksjfasdlkjf'"
      register: unobtainable
Run Code Online (Sandbox Code Playgroud)

sto*_*tic 6

为了能够在输出中尊重换行符以便您可以读取失败任务的标准输出,请将stdout_callback 更改为最小。

在您的 ansible.cfg 中,更改 stdout_callback 选项:

stdout_callback=minimal
Run Code Online (Sandbox Code Playgroud)

“最小”输出有点简洁,但它打印输出尊重换行符,以便您可以看到发生了什么:

 $ ansible-playbook playbooks/backUpWebsite.yml
 localhost | FAILED | rc=1 >>
 Traceback (most recent call last):
   File "<string>", line 1, in <module>
 NameError: name 'ksjfasdlkjf' is not defined

         to retry, use: --limit @<snip>/playbooks/backUpWebsite.retry
Run Code Online (Sandbox Code Playgroud)

我听到的其他东西可以工作

  • 您可以为标准输出编写自己的回调处理程序。 人们已经这样做了,而且看起来很简单,但我从未尝试过。

我尝试过但不起作用的事情:

三对。使用“ansible-playbook -vvv”。你会得到一大堆输出,其中确实包含了很好的断行的 json,但是 stdout 输出中的换行符没有打印出来,所以 stdout/stderr 仍然难以阅读:

$ ansible-playbook playbooks/backUpWebsite.yml -vvv
Using <snip>/ansible.cfg as config file

PLAYBOOK: backUpWebsite.yml ****************************************************
1 plays in playbooks/backUpWebsite.yml

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

TASK [command] *****************************************************************
task path: <snip>/playbooks/backUpWebsite.yml:6
Using module file <snip>/ansible/lib/ansible/modules/core/commands/command.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: <snip>
<127.0.0.1> EXEC /bin/sh -c 'echo ~ && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo <snip>/.ansible/tmp/ansible-tmp-1507083519.4247632-54588405727205 `" && echo ansible-tmp-1507083519.4247632-54588405727205="` echo <snip>/.ansible/tmp/ansible-tmp-1507083519.4247632-54588405727205 `" ) && sleep 0'
<127.0.0.1> PUT /tmp/tmpumtlourx TO <snip>/.ansible/tmp/ansible-tmp-1507083519.4247632-54588405727205/command.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x <snip>/.ansible/tmp/ansible-tmp-1507083519.4247632-54588405727205/ <snip>/.ansible/tmp/ansible-tmp-1507083519.4247632-54588405727205/command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '<snip>/anaconda3/bin/python <snip>/.ansible/tmp/ansible-tmp-1507083519.4247632-54588405727205/command.py; rm -rf "<snip>/.ansible/tmp/ansible-tmp-1507083519.4247632-54588405727205/" > /dev/null 2>&1 && sleep 0'
fatal: [localhost]: FAILED! => {
    "changed": true,
    "cmd": "python -c 'ksjfasdlkjf'",
    "delta": "0:00:00.037657",
    "end": "2017-10-03 20:18:39.843933",
    "failed": true,
    "invocation": {
        "module_args": {
            "_raw_params": "python -c 'ksjfasdlkjf'",
            "_uses_shell": true,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "warn": true
        },
        "module_name": "command"
    },
    "rc": 1,
    "start": "2017-10-03 20:18:39.806276",
    "stderr": "Traceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nNameError: name 'ksjfasdlkjf' is not defined",
    "stdout": "",
    "stdout_lines": [],
    "warnings": []
}
        to retry, use: --limit @<snip>/sys/ansible_readynet/playbooks/backUpWebsite.retry

PLAY RECAP *********************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1   
Run Code Online (Sandbox Code Playgroud)

信用

在 github针对 ansible发布了这个问题,希望说服人们 ansible 默认值非常无用。jhawkesworth 向我介绍了“最小”标准输出回调,很有帮助。

从那以后,我在 ansible 文档中找到了这个页面,该页面以非常不显眼的方式提到了这个插件。

恕我直言,这个从 ansible 获取可读错误输出的秘密对新用户来说完全隐藏了,我亲眼目睹了我认识的几个人在使用 ansible 时遇到的问题。

  • `stdout_callback=debug` 似乎也是一个不错的选择(最小不显示哪个任务繁忙)。 (2认同)