【问题标题】:Ansible - Print message - debug: msg="line1 \n {{ var2 }} \n line3 with var3 = {{ var3 }}"Ansible - 打印消息 - 调试:msg="line 1 \and {{ var2 }} \n line 3 with var 3 = {{ var 3 }}"
【发布时间】:2016-03-15 06:41:00
【问题描述】:

在 Ansible (1.9.4) 或 2.0.0 中

我执行了以下操作:

- debug: msg="line1 \n {{ var2 }} \n line3 with var3 = {{ var3 }}"

$ cat roles/setup_jenkins_slave/tasks/main.yml

- debug: msg="Installing swarm slave = {{ slave_name }} at {{ slaves_dir }}/{{ slave_name }}"
  tags:
    - koba

- debug: msg="1 == Slave properties = fsroot[ {{ slave_fsroot }} ], master[ {{ slave_master }} ], connectingToMasterAs[ {{ slave_user }} ], description[ {{ slave_desc }} ], No.Of.Executors[ {{ slave_execs }} ], LABELs[ {{ slave_labels }} ], mode[ {{ slave_mode }} ]"
  tags:
    - koba


- debug: msg="print(2 == Slave properties = \n\nfsroot[ {{ slave_fsroot }} ],\n master[ {{ slave_master }} ],\n connectingToMasterAs[ {{ slave_user }} ],\n description[ {{ slave_desc }} ],\n No.Of.Executors[ {{ slave_execs }} ],\n LABELs[ {{ slave_labels }} ],\n mode[ {{ slave_mode }} ])"
  tags:
    - koba

但这不是用新行打印变量(用于第三次调试操作)?

【问题讨论】:

    标签: action newline ansible roles ansible-playbook


    【解决方案1】:

    暂停模块:

    我发现显示带有格式的消息(例如:新行、制表符...)的最方便和简单的方法是使用pause 模块而不是debug 模块:

        - pause:
            seconds: 1
            prompt: |
              ======================
                line_1
                line_2
              ======================
    

    您还可以在提示中包含一个包含格式(新行、制表符...)的变量,它将按预期显示:

    - name: test
      hosts: all
      vars:
        line3: "\n  line_3"
      tasks:
        - pause:
            seconds: 1
            prompt: |
              /////////////////
                line_1
                line_2 {{ line3 }}
              /////////////////
    

    提示:

    当您想要显示命令的输出时,而不是运行额外的任务来运行命令并注册输出,您可以直接使用提示符内的管道查找并一次性完成工作:

        - pause:
            seconds: 1
            prompt: |
              =========================
                line_1
                {{ lookup('pipe', 'echo "line_2 with \t tab \n  line_3 "') }}
                line_4
              =========================
    

    关于暂停模块的额外说明:

    1. 如果您有多个主机,请注意pause 任务将运行 仅针对主机列表中的第一个主机一次。

      这意味着如果你要显示的变量只存在于 部分主机和第一台主机不包含该变量 那么你会得到一个错误。

      为避免此类问题,请使用{{ hostvars['my_host']['my_var'] }} 而不是{{ my_var }}

    2. 结合pausewhen 条件可能会跳过任务!为什么? 因为该任务只会针对第一个主机运行一次 可能不符合规定的when 条件。

      为避免这种情况,请勿使用限制数量的条件 主机!因为你也不需要它,因为你知道任务会 无论如何只运行一次。也使用上述hostvars 来确保 无论拾取的主机是什么,您都会获得所需的变量。

    例子:

    不正确:

    - name: test
      hosts: host1,host2
      vars:
        display_my_var: true
      tasks:
        - when: inventory_hostname == 'host2'
          set_fact:
            my_var: "hi there"
        - when:
          - display_my_var|bool
          - inventory_hostname == 'host2'
          pause:
            seconds: 1
            prompt: |
              {{ my_var }}
    

    这个例子会跳过暂停任务,因为它只会选择第一个主机host1然后开始评估条件,当它发现host1不符合第二个条件时它会跳过这个任务。

    正确:

    - name: test
      hosts: host1,host2
      vars:
        display_my_var: true
      tasks:
        - when: inventory_hostname == 'host2'
          set_fact:
            my_var: "hi there"
        - when: display_my_var|bool
          pause:
            seconds: 1
            prompt: |
              {{ hostvars['host2']['my_var'] }}
    

    另一个显示内容取决于主机的消息的示例:

        - set_fact:
            my_var: "hi from {{ inventory_hostname }}"
        - pause:
            seconds: 1
            prompt: |
              {% for host in ansible_play_hosts %}
                {{ hostvars[host]['my_var'] }}
              {% endfor %}
    

    【讨论】:

    • 感谢分享@Ejez
    • 到目前为止最好的答案。我很惊讶没有更好的方法来做到这一点。请注意,seconds 可以设置为 0
    • @Fmstrat 效果不大。 (“从 2.2 开始,如果你指定 0 或负数表示分钟或秒,它将等待 1 秒,之前它会无限期地等待。”)
    【解决方案2】:

    我想打印到控制台的日志文件有类似的问题。 split("\n") 工作正常,但它在每一行添加可见的\n,所以我找到了更好的方法

      tasks:
    - name: Read recent lines from logfile for service {{ appName }}
      shell: tail -n 1000 {{ logFile }}
      register: appNameLogFile
    
    - debug:
        msg: "This is a stdout lines"
      with_items: "{{ appNameLogFile.stdout }}"
    

    它遍历appNameLogFile 的每一行,并作为副作用将这一行打印到控制台中。您可以将其更新为

            msg: "This is a stdout lines: {{ item }}"
    

    但在我的情况下不需要

    【讨论】:

      【解决方案3】:

      您可以使用寄存器变量的stdout_lines

      - name: Do something
        shell: "ps aux"
        register: result
      
      - debug: var=result.stdout_lines
      

      【讨论】:

        【解决方案4】:

        [:-1]抑制apt的最后一个空字符串

        ---
        - name: 'apt: update & upgrade'
          apt:
            update_cache: yes
            cache_valid_time: 3600
            upgrade: safe
          register: apt
        - debug: msg={{ apt.stdout.split('\n')[:-1] }}
        

        由于.split('\n'),上面的debug: 行产生了很好的换行符,并且由于[:-1] 而抑制了最后一个空字符串;当然,所有这些都是 Python 字符串操作。

        "msg": [
            "Reading package lists...", 
            "Building dependency tree...", 
            "Reading state information...", 
            "Reading extended state information...", 
            "Initializing package states...", 
            "Building tag database...", 
            "No packages will be installed, upgraded, or removed.", 
            "0 packages upgraded, 0 newly installed, 0 to remove and 0 not upgraded.", 
            "Need to get 0 B of archives. After unpacking 0 B will be used.", 
            "Reading package lists...", 
            "Building dependency tree...", 
            "Reading state information...", 
            "Reading extended state information...", 
            "Initializing package states...", 
            "Building tag database..."
        ]
        

        【讨论】:

        • 你可以用stdout_lines代替stdout.split('\n')
        【解决方案5】:

        调试模块支持数组,所以你可以这样做:

        debug:
          msg:
            - "First line"
            - "Second line"
        

        输出:

        ok: [node1] => {
            "msg": [
                "First line",
                "Second line"
            ]
        }
        

        或者你可以使用这个答案中的方法:

        In YAML, how do I break a string over multiple lines?

        【讨论】:

        • 很高兴知道,很方便。文档应该提到这一点。
        • @guoqiao - 文档确实提到了这一点:debug_module 文档中有一个相应的示例。
        【解决方案6】:

        我发现使用调试打印多行文本最方便的方法是:

        - name: Print several lines of text
          vars:
            msg: |
                 This is the first line.
                 This is the second line with a variable like {{ inventory_hostname }}.
                 And here could be more...
          debug:
            msg: "{{ msg.split('\n') }}"
        

        它将消息拆分为一个数组并调试将每一行打印为一个字符串。输出是:

        ok: [example.com] => {
            "msg": [
                "This is the first line.", 
                "This is the second line with a variable like example.com", 
                "And here could be more...", 
                ""
            ]
        }
        

        感谢jhutar

        【讨论】:

          【解决方案7】:

          我在@Bruce P 关于通过 sed 的管道输出的回答中挖掘了一下,这就是我想出的:

          ansible-playbook [blablabla] | sed 's/\\n/\n/g'
          

          如果有人感兴趣。

          【讨论】:

          • 该不该:在这里做点什么 | sed "s#\\\n#\n#" 即 \\\ vs \\ 用于替换的单词。
          • 我也在寻找同样的东西。谢谢
          • 有什么好方法可以将 sed 打包成别名或 bash 脚本?喜欢:ansible-playbook ... | sednl
          【解决方案8】:

          作为一种解决方法,我使用了 with_items,它对我来说有点用。

          - debug: msg="Installing swarm slave = {{ slave_name }} at {{ slaves_dir }}/{{ slave_name }}"
          
          - debug: msg="Slave properties = {{ item.prop }} [ {{ item.value }} ]"
            with_items:
             - { prop: 'fsroot', value: "{{ slave_fsroot }}" }
             - { prop: 'master', value: "{{ slave_master }}" }
             - { prop: 'connectingToMasterAs', value: "{{ slave_user }}" }
             - { prop: 'description', value: "{{ slave_desc }}"  }
             - { prop: 'No.Of.Executors', value: "{{ slave_execs }}" }
             - { prop: 'LABELs', value: "{{ slave_labels }}" }
             - { prop: 'mode', value: "{{ slave_mode }}" }
            tags:
              - koba
          

          【讨论】:

          • 如果可以以某种方式压缩结果输出会很棒。我现在用它作为替身,但应该占用一行的内容占用了七行:(
          • 是的。我认为这是 JINJA 的限制。
          【解决方案9】:

          这是discussed here。简而言之,您要么需要通过 sed 管道输出以将 \n 转换为实际的换行符,要么您需要编写一个回调插件来为您执行此操作。

          【讨论】:

          • 我的意思是,我可以使用 shell 或命令模块并回显它们 acc。到我想要的。我也可以使用 with_lines: 和我们要打印的行(每行)。我还可以注册命令/shell 的输出以使用新行打印这些行,并使用 register_var.stdout_lines 显示这些行,但在调试操作中,msg="...\n...\n",我在某处看到我可以使用 print ( ) 函数,它不会给我一个错误,但也不会每行打印变量(就像我想要的那样)。您提到了 sed,我可以在哪里以及如何在“-调试”操作中使用 sed?
          • 看看我链接到的问题。
          • 我明白了。使用 sed 和 |在整个 ansible/ansible-playbook 命令结束时,我猜想的目的会失败,但它可以作为一种解决方法。谢谢。在同一篇文章中,我看到了接下来我会尝试的回调插件。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-06-28
          • 2020-11-24
          • 2021-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-27
          相关资源
          最近更新 更多