How to save stdout_lines to a file without losing the newlines

Hi everyone,

Considering a variable {{ table.stdout_lines ]] containing the following when printing it out on the terminal:

TASK [save_table : Printing the returned table] *****************************************************************************************************************************
ok: [IOSv_L2_10] => {
“table.stdout_lines”: [
[
“Extended IP access list authorized-snmp-nms”,
" 10 permit ip host 172.21.100.1 host 172.21.100.210 log",
“Extended IP access list preauth_ipv4_acl (per-user)”,
" 10 permit udp any any eq domain",
" 20 permit tcp any any eq domain",
" 30 permit udp any eq bootps any",
" 40 permit udp any any eq bootpc",
" 50 permit udp any eq bootpc any",
" 60 deny ip any any",
“IPv6 access list preauth_ipv6_acl (per-user)”,
" permit udp any any eq domain sequence 10",
" permit tcp any any eq domain sequence 20",
" permit icmp any any nd-ns sequence 30",
" permit icmp any any nd-na sequence 40",
" permit icmp any any router-solicitation sequence 50",
" permit icmp any any router-advertisement sequence 60",
" permit icmp any any redirect sequence 70",
" permit udp any eq 547 any eq 546 sequence 80",
" permit udp any eq 546 any eq 547 sequence 90",
" deny ipv6 any any sequence 100"
]
]
}

I need to save those lines into a local file, easy right?

  • name: Saving “{{ item }}” into local file
    local_action: copy content=“{{ table.stdout_lines }}” dest=“{{ dest_file }}”

Unfortunately, all newlines are lost rendering the file difficult to read:
[[“Extended IP access list authorized-snmp-nms”, " 10 permit ip host 172.21.100.1 host 172.21.100.210 log", “Extended IP access list preauth_ipv4_acl (per-user)”, " 10 permit udp any any eq domain", " 20 permit tcp any any eq domain", " 30 permit udp any eq bootps any", " 40 permit udp any any eq bootpc", " 50 permit udp any eq bootpc any", " 60 deny ip any any", “IPv6 access list preauth_ipv6_acl (per-user)”, " permit udp any any eq domain sequence 10", " permit tcp any any eq domain sequence 20", " permit icmp any any nd-ns sequence 30", " permit icmp any any nd-na sequence 40", " permit icmp any any router-solicitation sequence 50", " permit icmp any any router-advertisement sequence 60", " permit icmp any any redirect sequence 70", " permit udp any eq 547 any eq 546 sequence 80", " permit udp any eq 546 any eq 547 sequence 90", " deny ipv6 any any sequence 100"]]

Anyone has a brilliant simple idea to save {{ table.stdout_lines }} with all newlines in the file?

Yes, use table.stdout :slight_smile:

Have you tried the following?

{{table.stdout_lines|join(‘\n’) }}

Not tested but sounds like it might do what you want.

Jon

@Kai Stian Olstad: stdout adds literal ‘\n’ to each line

@Jon: |join(‘\n’) has no effect on stdout_lines

However, if I combine both proposals into table.stdout|join(‘\n’), it works! Thanks guys :wink:

For instance:

Mac Address Table

That's strange, i use that all the time and get correct newlines.

I suppose it depends on how the data are returned by the target device, which is not a Linux server here, but a Cisco IOS networking device, which is a very specific beast.

Write the stdout var instead.

  • name: Saving “{{ item }}” into local file
    local_action: copy content=“{{ table.stdout[0] }}” dest=“{{ dest_file }}”

Thanks, it’s even simpler and it seems to function correctly in all cases.

@Peter Sprygada: I’m now facing a more complicated case where I have trouble accessing stdout[0]:

  • name: Fetching PACL_Table on all L2 interfaces from the remote node
    ios_command:
    provider: “{{ connections.ssh }}”
    commands:

  • “show run interface {{ net_item.key }} | include ^interface|access-group”
    with_dict: “{{ ansible_net_interfaces }}”
    when: net_item.value.ipv4.address is not defined
    loop_control:
    loop_var: net_item
    register: pacl_tables

  • name: Printing pacl_tables.results
    debug: var=pacl_tables.results

…leads to:

ok: [IOSv_L2_10] => {
“pacl_tables.results”: [
{
“_ansible_item_label”: {
“key”: “GigabitEthernet1/2”,
“value”: {
“bandwidth”: 1000000,
“description”: “Connected to [u’IOSv_Leaf_16.actionmystique.net’] on its port [u’Gi0/0’]”,
“duplex”: “Full”,
“ipv4”: null,
“lineprotocol”: "up (connected) ",
“macaddress”: “0036.2586.7e06”,
“mediatype”: “unknown media type”,
“mtu”: 1500,
“operstatus”: “up”,
“type”: “iGbE”
}
},
“_ansible_item_result”: true,
“_ansible_no_log”: false,
“_ansible_parsed”: true,
“changed”: false,
“invocation”: {
“module_args”: {
“auth_pass”: “VALUE_SPECIFIED_IN_NO_LOG_PARAMETER”,
“authorize”: true,
“commands”: [
“show run interface GigabitEthernet1/2 | include ^interface|access-group”
],
“host”: “172.21.100.210”,
“interval”: 1,
“match”: “all”,
“password”: “VALUE_SPECIFIED_IN_NO_LOG_PARAMETER”,
“port”: 22,
“provider”: {
“auth_pass”: “VALUE_SPECIFIED_IN_NO_LOG_PARAMETER”,
“authorize”: true,
“host”: “172.21.100.210”,
“password”: “VALUE_SPECIFIED_IN_NO_LOG_PARAMETER”,
“port”: 22,
“ssh_keyfile”: “~/.ssh/id_rsa”,
“timeout”: 10,
“transport”: “cli”,
“username”: “admin”,
“version”: 2
},
“retries”: 10,
“ssh_keyfile”: “/root/.ssh/id_rsa”,
“timeout”: 10,
“transport”: “cli”,
“use_ssl”: true,
“username”: “admin”,
“validate_certs”: true,
“wait_for”: null
},
“module_name”: “ios_command”
},
“net_item”: {
“key”: “GigabitEthernet1/2”,
“value”: {
“bandwidth”: 1000000,
“description”: “Connected to [u’IOSv_Leaf_16.actionmystique.net’] on its port [u’Gi0/0’]”,
“duplex”: “Full”,
“ipv4”: null,
“lineprotocol”: "up (connected) ",
“macaddress”: “0036.2586.7e06”,
“mediatype”: “unknown media type”,
“mtu”: 1500,
“operstatus”: “up”,
“type”: “iGbE”
}
},
“stdout”: [
“show run interface GigabitEthernet1/2 | include ^interface|access-$terface GigabitEthernet1/2 | include ^interface|access-g oup\ninterface GigabitEthernet1/2”
],
“stdout_lines”: [
[
“show run interface GigabitEthernet1/2 | include ^interface|access-$terface GigabitEthernet1/2 | include ^interface|access-g oup”,
“interface GigabitEthernet1/2”
]
],
“warnings”:
},

…repeated n times, for all found L2 interfaces.

However, I cannot access stdout[0] for all these interfaces with:

  • name: Printing pacl_tables.results.stdout
    debug: var=print_item.stdout[0]
    with_dict: “{{ pacl_tables.results }}”
    loop_control:
    loop_var: print_item
    … which leads to:

fatal: [IOSv_L2_10]: FAILED! => {“failed”: true, “msg”: “with_dict expects a dict”}

How can we correctly access a table of results? (I’m not mentioning the issue with the strange result itself.)