Debugging 如何调试可解释的问题?

Debugging 如何调试可解释的问题?,debugging,ansible,Debugging,Ansible,有时,ansible不做你想做的事。越来越冗长也无济于事。例如,我现在尝试启动coturnserver,它在systemdOS(Debian Jessie)上附带init脚本。Ansible认为它在运行,但它不是。我如何调查引擎盖下发生的事情?执行哪些命令,输出/退出代码是什么?调试模块 最基本的方法是在执行行中添加-vvv,以更详细的级别运行ansible/ansible playbook 用Python(Linux/Unix)编写的模块最彻底的方法是运行ansible/ansible pl

有时,
ansible
不做你想做的事。越来越冗长也无济于事。例如,我现在尝试启动
coturn
server,它在
systemd
OS(Debian Jessie)上附带init脚本。Ansible认为它在运行,但它不是。我如何调查引擎盖下发生的事情?执行哪些命令,输出/退出代码是什么?

调试模块

  • 最基本的方法是在执行行中添加
    -vvv
    ,以更详细的级别运行
    ansible
    /
    ansible playbook

  • 用Python(Linux/Unix)编写的模块最彻底的方法是运行
    ansible
    /
    ansible playbook
    ,环境变量
    ansible\u KEEP\u REMOTE\u FILES
    设置为
    1
    (在控制机器上)

    它使Ansible在目标机器上保留它执行(成功或失败)的Python脚本的精确副本

    脚本的路径打印在Ansible日志中,对于常规任务,脚本存储在SSH用户的主目录下:
    ~/.Ansible/tmp/

    脚本中嵌入了确切的逻辑,具体取决于每个模块。有些人将Python与标准库或外部库一起使用,有些人调用外部命令

调试剧本

  • 与调试模块类似,使用
    -vvv
    参数增加冗余级别会导致更多数据打印到Ansible日志

  • 由于Ansible 2.1 a允许调试交互失败的任务:检查、修改数据;重新运行任务

调试连接

  • -vvvv
    参数添加到
    ansible
    /
    ansible playbook
    调用会导致日志包含连接的调试信息

    • 以下是我的想法

      Ansible将模块发送到目标系统并在那里执行。所以,若您在本地更改模块,您的更改将在运行playbook时生效。在我的机器上,模块位于
      /usr/lib/python2.7/site packages/ansible/modules
      ansible-2.1.2.0
      )。而
      服务
      模块位于。Anisable(在
      模块_utils/basic.py中声明的类实例)有一个方法,该方法将消息发送到systemd日志(如果可用),或者返回到
      syslog
      。因此,在目标系统上运行
      journalctl-f
      ,在本地模块中添加调试语句(
      module.log(msg='test')
      ),然后运行您的playbook。您将在
      ansible basic.py
      unit name下看到调试语句

      此外,当您使用
      -vvv
      运行
      ansible playbook
      时,您可以在
      systemd
      日志中看到一些调试输出,至少可以看到调用消息和错误消息(如果有)

      还有一件事,如果您尝试调试使用
      pdb
      本地运行的代码(
      import pdb;pdb.set_trace()
      ),您很可能会遇到
      bdbguit
      异常。这是因为
      python
      在创建线程(
      ansible
      worker)时。这里的解决方案是在运行
      pdb之前重新打开
      stdin
      。按照建议设置跟踪()


      调试角色/剧本

      基本上,在大型网络上调试大型库存上的ansible自动化就是调试分布式网络应用程序。它可能非常乏味和微妙,并且没有足够的用户友好工具

      因此,我相信你的问题的答案也是我之前所有答案的结合+小加法。因此,这里:

      • 绝对强制性:你必须想知道发生了什么,也就是说,你正在自动化什么,你期望发生什么。e、 g.ansible未能检测到systemd单元正在运行或已停止的服务通常意味着服务单元文件或服务模块中存在错误,因此您需要1。识别错误,2。向供应商/社区报告缺陷,3。提供TODO和bug链接的解决方法。4.当bug修复后-删除您的解决方法

      • 为了使代码更易于调试,请尽可能多地使用模块

      • 为所有任务和变量指定有意义的名称

      • 使用静态代码分析工具,如
        ansible lint
        。这可以避免你犯一些愚蠢的小错误

      • 利用冗余标志和日志路径

      • 明智地使用
        调试
        模块

      • “了解你的事实”-有时将目标机器事实转储到文件中并将其拉到ansible master中是有用的

        • 使用
          strategy:debug
          在某些情况下,您可能会错误地陷入任务调试器。然后可以评估任务正在使用的所有参数,并决定下一步要做什么

        • 最后一种方法是使用Python调试器,将其附加到本地ansible运行和/或执行模块的远程Python。这通常很棘手:您需要允许机器上的其他端口打开,并且如果打开端口的代码是导致问题的代码

      此外,有时“看一边”也很有用—连接到目标主机并提高其可调试性(更详细的日志记录)

      当然,日志收集可以更容易地跟踪由于ansible操作而发生的更改

      正如您所看到的,与任何其他分布式应用程序和框架一样,调试能力仍然不是我们所希望的

      过滤器/插件

      这基本上是Python开发,与任何Python应用程序一样调试

      模块


      根据技术的不同,以及您需要同时查看本地和远程发生的情况,您最好选择易于远程调试的语言。

      可能需要多个级别的调试,但最简单的是添加
      ANSIBLE\u STRATEGY=debug
      环境
      sys.stdin = open('/dev/tty')
      import pdb; pdb.set_trace()
      
      - name: my task
        shell: "bash somescript.sh"
        register: output
      
      - debug:
        msg: "{{ output.rc }}"
      
      - name: Create the master server certificate
        command: >
          {{ hostvars[openshift_ca_host]['first_master_client_binary'] }} adm ca create-server-cert
          {% for named_ca_certificate in openshift.master.named_certificates | default([]) | lib_utils_oo_collect('cafile') %}
          --certificate-authority {{ named_ca_certificate }}
          {% endfor %}
          {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | lib_utils_oo_collect('path') %}
          --certificate-authority {{ legacy_ca_certificate }}
          {% endfor %}
          --hostnames={{ hostvars[item].openshift.common.all_hostnames | join(',') }}
          --cert={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.crt
          --key={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.key
          --expire-days={{ openshift_master_cert_expire_days }}
          --signer-cert={{ openshift_ca_cert }}
          --signer-key={{ openshift_ca_key }}
          --signer-serial={{ openshift_ca_serial }}
          --overwrite=false
        when: item != openshift_ca_host
        with_items: "{{ hostvars
                        | lib_utils_oo_select_keys(groups['oo_masters_to_config'])
                        | lib_utils_oo_collect(attribute='inventory_hostname', filters={'master_certs_missing':True}) }}"
        delegate_to: "{{ openshift_ca_host }}"
        run_once: true
      
      master0] TASK: openshift_master_certificates : Create the master server certificate (debug)> p task.args
      {u'_raw_params': u"{{ hostvars[openshift_ca_host]['first_master_client_binary'] }} adm ca create-server-cert {% for named_ca_certificate in openshift.master.named_certificates | default([]) | lib_utils_oo_collect('cafile') %} --certificate-authority {{ named_ca_certificate }} {% endfor %} {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | lib_utils_oo_collect('path') %} --certificate-authority {{ legacy_ca_certificate }} {% endfor %} --hostnames={{ hostvars[item].openshift.common.all_hostnames | join(',') }} --cert={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.crt --key={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.key --expire-days={{ openshift_master_cert_expire_days }} --signer-cert={{ openshift_ca_cert }} --signer-key={{ openshift_ca_key }} --signer-serial={{ openshift_ca_serial }} --overwrite=false"}
      [master0] TASK: openshift_master_certificates : Create the master server certificate (debug)> exit