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

ActionNewlineAnsibleRolesAnsible Playbook

Action Problem Overview


In Ansible (1.9.4) or 2.0.0

I ran the following action:

- 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

But this is not printing the variable with new lines (for the 3rd debug action)?

Action Solutions


Solution 1 - Action

debug module support array, so you can do like this:

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

The output:

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

Or you can use the method from this answer:

https://stackoverflow.com/questions/3790454/in-yaml-how-do-i-break-a-string-over-multiple-lines

Solution 2 - Action

The most convenient way I found to print multi-line text with debug is:

- 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') }}"

It splits the message up into an array and debug prints each line as a string. The output is:

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...", 
        ""
    ]
}

Thanks to jhutar.

Solution 3 - Action

Pause module:

The most convenient and simple way I found to display a message with formatting (ex: new lines, tabs ...) is to use the pause module instead of debug module:

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

You can also include a variable that contains formatting (new lines, tabs...) inside the prompt and it will be displayed as expected:

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

Tip:

when you want to display an output from a command, and instead of running an extra task to run the command and register the output, you can directly use the pipe lookup inside the prompt and do the job in one shot:

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

Extra notes regarding the pause module:
  1. If you have multiple hosts, note that the pause task will run only once against the first host in the list of hosts.

    This means that if the variable you want to display exists only in part of the hosts and the first host does not contain that variable then you will get an error.

    To avoid such an issue, use {{ hostvars['my_host']['my_var'] }} instead of {{ my_var }}

  2. Combining pause with when conditional might skip the task! Why? Because the task will only run once against the first host which might not conform to the stated when conditions.

    To avoid this, don't use conditions that constrain the number of hosts! As you don't need it either, because you know that the task will run only once anyway. Also use hostvars stated above to make sure you get the needed variable whatever the picked up host is.

Example:

Incorrect:

- 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 }}

This example will skip the pause task, because it will choose only the first host host1 and then starts to evaluate conditions, when it finds that host1 is not conforming to the second condition it will skip the task.

Correct:

- 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'] }}

Another example to display messages where the content depends on the host:

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

Solution 4 - Action

Suppressing the last empty string of apt with [:-1]

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

The above debug: line results in nice line breaks, due to .split('\n'), and a suppressed last empty string thanks to [:-1]; all of which is Python string manipulation, of course.

"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..."
]

Solution 5 - Action

You could use stdout_lines of register variable:

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

- debug: var=result.stdout_lines

Solution 6 - Action

I dig a bit on @Bruce P answer about piping output through sed, and this is what I came up to :

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

if anyone is interested.

Solution 7 - Action

This is discussed here. In short you either need to pipe your output through sed to convert the \n to an actual newline, or you need to write a callback plugin to do this for you.

Solution 8 - Action

As a workaround, I used with_items and it kind of worked for me.

- 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

Solution 9 - Action

I had similar problem with log file which I wanted to print to console. split("\n") works fine but it adds visible \n to each line so I found nicer way

  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 }}"

It iterates over each line from appNameLogFile and as the side effect prints this line into the console. You can update it to

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

but in my case it was not needed

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAKSView Question on Stackoverflow
Solution 1 - ActiondiabloneoView Answer on Stackoverflow
Solution 2 - ActionmaikelView Answer on Stackoverflow
Solution 3 - ActionEjezView Answer on Stackoverflow
Solution 4 - ActionSerge StroobandtView Answer on Stackoverflow
Solution 5 - ActionEugene LopatkinView Answer on Stackoverflow
Solution 6 - ActionedelansView Answer on Stackoverflow
Solution 7 - ActionBruce PView Answer on Stackoverflow
Solution 8 - ActionAKSView Answer on Stackoverflow
Solution 9 - ActionDamianView Answer on Stackoverflow