Ansible - 打印信息 - debug: msg="第一行 \n {{ var2 }} \n 第三行有变量 var3 = {{ var3 }}"

88

在 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

但是这不会使用换行符打印变量吗(对于第三个调试操作)?

9个回答

109

调试模块支持数组,因此您可以这样做:

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

输出:

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

或者您可以使用来自此答案的方法:

在YAML中,如何将一个字符串分成多行?


很好知道,非常方便。文档应该提到这一点。 - guoqiao
1
@ guoqiao - 文档确实提到了这一点:在debug_module文档中有一个相应的示例。 - Tomáš Pospíšek

86

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

- 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


32

暂停模块:

我发现显示具有格式的消息(例如:新行,制表符等)最方便简单的方法是使用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 %}

1
感谢@Ejez的分享。 - AKS
3
目前为止,这是最好的答案。我很惊讶居然没有更好的方法来做这件事。需要注意的是,“seconds”可以设为“0”。 - Fmstrat
2
@Fmstrat 的作用不大。("从2.2版本开始,如果您指定分钟或秒数为0或负数,它将等待1秒钟,之前它会无限期地等待。") - muru
1
有没有办法隐藏暂停模块打印的所有垃圾信息?对我来说,我得到了所有这些杂乱无章的信息:TASK [git_sync : pause] ******************************************************** 暂停1秒钟 (ctrl+C然后'C'=提前继续,ctrl+C然后'A'=中止) [git_sync : pause] - Ben Farmer

12

您可以使用注册变量的 stdout_lines

- name: Do something
  shell: "ps aux"
  register: result

- debug: var=result.stdout_lines

1
如果您只是想要一个命令输出,那么这是最简单的解决方案。 - NeilWang

10

使用[:-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] }}

上面的debug:行由于使用.split('\n'),产生了很好的换行效果,并且由于[:-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..."
]

2
你可以使用stdout_lines代替stdout.split('\n') - andras.tim

6

我对@Bruce P提到的通过sed管道输出进行了一些研究,这是我的结果:

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

如果有任何人感兴趣的话。

应该这样做:在此处执行某些操作,然后使用命令“sed”将“\\n”替换为“\n”,即要被替换的单词中使用“\\”而不是“\”。 - AKS
1
我也在寻找同样的东西。谢谢。 - Prakash
有没有好的方法将sed打包成别名或bash脚本? 例如:ansible-playbook ... | sednl - Leo Ufimtsev

3
这个问题在这里有讨论。简而言之,您需要通过sed将输出转换为实际换行符,或者编写回调插件来代替您执行此操作。

我的意思是,我可以使用shell或command模块,并根据我的要求进行回显。我还可以使用with_lines:<cmd>并使用行(每行)进行打印。我还可以注册命令/ shell的输出以打印这些行,并使用register_var.stdout_lines显示这些行,但在debug操作中,msg =“…\n…\n”,我看到有人说我可以使用print()函数,它没有给我错误,但也没有按行打印变量(就像我想要的那样)。您提到了sed,在“-debug”操作中我应该在哪里以及如何使用sed? - AKS
请看我链接的问题。 - Bruce P
我明白了。我猜在整个ansible/ansible-playbook命令的末尾使用sed |将会失去其意义,但这将作为一种解决方法。谢谢。在同一篇帖子中,我看到了回调插件,下次我会尝试一下。 - AKS

1
作为一种解决方法,我使用了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

如果能将输出结果进行压缩就太好了。目前我正在使用这个替代方案,但本应只占用一行的内容却占用了七行的空间:( - 3cheesewheel
是的,我认为这是JINJA的限制。 - AKS

1
我曾遇到类似的问题,需要将日志文件输出到控制台。使用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 }}"

但在我的情况下不需要它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接