You may have a look into debug – Print statements during execution, Using Variables and Return Values.
Copy---
- hosts: localhost
become: true
gather_facts: false
vars:
RESULT:
STDOUT_LINES:
- "# name admin@shrrah.esquimail.com"
- "zimbraIsDelegatedAdminAccount: FALSE"
- ""
- "# name prueba5@prueba5.com"
- ""
- "# name prueba7@prueba7.com"
- "zimbraIsDelegatedAdminAccount: TRUE"
- ""
- "# name prueba9@prueba9.com"
tasks:
- name: Show STDOUT_LINES
debug:
msg: "{{ RESULT.STDOUT_LINES }}"
resulting into an output only of
CopyTASK [Show STDOUT_LINES] *****************
ok: [localhost] =>
msg:
- '# name admin@shrrah.esquimail.com'
- 'zimbraIsDelegatedAdminAccount: FALSE'
- ''
- '# name prueba5@prueba5.com'
- ''
- '# name prueba7@prueba7.com'
- 'zimbraIsDelegatedAdminAccount: TRUE'
- ''
- '# name prueba9@prueba9.com'
and if Ansible Callback plugin is configured to YAML instead of JSON.
To get lines containing certain strings only you may Loop over the list based on a Condition
Copy - name: Show lines with TRUE only
debug:
msg: "{{ item }}"
when: "'TRUE' in item"
loop: "{{ RESULT.STDOUT_LINES }}"
resulting into an output of
CopyTASK [Show lines with TRUE only] *******************************
ok: [localhost] => (item=zimbraIsDelegatedAdminAccount: TRUE) =>
msg: 'zimbraIsDelegatedAdminAccount: TRUE'
Further Documenation
- Index of all Callback Plugins
If you like to have the line before included, you could use an approach like
Copy - name: Show lines with TRUE and line before
debug:
msg: "{{ RESULT.STDOUT_LINES[ansible_loop.index0 - 1] }}\n{{ item }}"
when: "'TRUE' in item"
loop: "{{ RESULT.STDOUT_LINES }}"
loop_control:
extended: true
label: "{{ ansible_loop.index0 }}"
resulting into an output of
CopyTASK [Show lines with TRUE and line before] *************************************************************************************************************************************
ok: [localhost] => (item=6) =>
msg: |-
# name prueba7@prueba7.com
zimbraIsDelegatedAdminAccount: TRUE
Further Documentation
- Extended loop variables
Since you are using the shell module, you could use also an approach like
Copy- name: DELEGATED ADMIN ACCOUNTS - check, get and send to the file domain.list
shell:
cmd: /opt/zimbra/bin/zmprov -l gaaa -v zimbraIsDelegatedAdminAccount | grep -B 1 TRUE
and gather only result lines which are true an the line before.
Further Q&A
grepa file, but show several surrounding lines?
Regarding
... send it to the
file.txt
you may have a look into
- Ansible - Save registered variable to file
- Ansible: Save registered variables to file
- ...
You may have a look into debug – Print statements during execution, Using Variables and Return Values.
Copy---
- hosts: localhost
become: true
gather_facts: false
vars:
RESULT:
STDOUT_LINES:
- "# name admin@shrrah.esquimail.com"
- "zimbraIsDelegatedAdminAccount: FALSE"
- ""
- "# name prueba5@prueba5.com"
- ""
- "# name prueba7@prueba7.com"
- "zimbraIsDelegatedAdminAccount: TRUE"
- ""
- "# name prueba9@prueba9.com"
tasks:
- name: Show STDOUT_LINES
debug:
msg: "{{ RESULT.STDOUT_LINES }}"
resulting into an output only of
CopyTASK [Show STDOUT_LINES] *****************
ok: [localhost] =>
msg:
- '# name admin@shrrah.esquimail.com'
- 'zimbraIsDelegatedAdminAccount: FALSE'
- ''
- '# name prueba5@prueba5.com'
- ''
- '# name prueba7@prueba7.com'
- 'zimbraIsDelegatedAdminAccount: TRUE'
- ''
- '# name prueba9@prueba9.com'
and if Ansible Callback plugin is configured to YAML instead of JSON.
To get lines containing certain strings only you may Loop over the list based on a Condition
Copy - name: Show lines with TRUE only
debug:
msg: "{{ item }}"
when: "'TRUE' in item"
loop: "{{ RESULT.STDOUT_LINES }}"
resulting into an output of
CopyTASK [Show lines with TRUE only] *******************************
ok: [localhost] => (item=zimbraIsDelegatedAdminAccount: TRUE) =>
msg: 'zimbraIsDelegatedAdminAccount: TRUE'
Further Documenation
- Index of all Callback Plugins
If you like to have the line before included, you could use an approach like
Copy - name: Show lines with TRUE and line before
debug:
msg: "{{ RESULT.STDOUT_LINES[ansible_loop.index0 - 1] }}\n{{ item }}"
when: "'TRUE' in item"
loop: "{{ RESULT.STDOUT_LINES }}"
loop_control:
extended: true
label: "{{ ansible_loop.index0 }}"
resulting into an output of
CopyTASK [Show lines with TRUE and line before] *************************************************************************************************************************************
ok: [localhost] => (item=6) =>
msg: |-
# name prueba7@prueba7.com
zimbraIsDelegatedAdminAccount: TRUE
Further Documentation
- Extended loop variables
Since you are using the shell module, you could use also an approach like
Copy- name: DELEGATED ADMIN ACCOUNTS - check, get and send to the file domain.list
shell:
cmd: /opt/zimbra/bin/zmprov -l gaaa -v zimbraIsDelegatedAdminAccount | grep -B 1 TRUE
and gather only result lines which are true an the line before.
Further Q&A
grepa file, but show several surrounding lines?
Regarding
... send it to the
file.txt
you may have a look into
- Ansible - Save registered variable to file
- Ansible: Save registered variables to file
- ...
Create a dictionary
Copy - set_fact:
info: "{{ info|d({})|combine({_key: _val}) }}"
loop: "{{ stdout.split('#')[1:] }}"
vars:
_list: "{{ item.split('\n')|map('trim') }}"
_key: "{{ _list.0.split(' ')|last }}"
_val: "{{ _list[1:]|select()|map('from_yaml')|combine }}"
gives
Copy info:
admin@shrrah.esquimail.com:
zimbraIsDelegatedAdminAccount: false
prueba5@prueba5.com: {}
prueba7@prueba7.com:
zimbraIsDelegatedAdminAccount: true
prueba9@prueba9.com: {}
Then, the template is trivial. Either print all items
Copy - copy:
content: |-
{% for k,v in info.items() %}
{{ k }}
{{ v|to_nice_yaml }}
{% endfor %}
dest: file.txt
gives
Copyshell> cat file.txt
admin@shrrah.esquimail.com
zimbraIsDelegatedAdminAccount: false
prueba5@prueba5.com
{}
prueba7@prueba7.com
zimbraIsDelegatedAdminAccount: true
prueba9@prueba9.com
{}
, or explicitly select item(s)
Copy - copy:
content: |-
prueba7@prueba7.com
{{ info['prueba7@prueba7.com']|to_nice_yaml }}
dest: file.txt
gives
Copyshell> cat file.txt
prueba7@prueba7.com
zimbraIsDelegatedAdminAccount: true
Note
Additional attributes will be parsed too, e.g.
Copy stdout_lines: [
"# name admin@shrrah.esquimail.com",
"zimbraIsDelegatedAdminAccount: FALSE",
"",
"# name prueba5@prueba5.com",
"",
"# name prueba7@prueba7.com",
"zimbraIsDelegatedAdminAccount: TRUE",
"zimbraIsDelegatedRootAccount: TRUE",
"",
"# name prueba9@prueba9.com"
]
will give
Copy info:
admin@shrrah.esquimail.com:
zimbraIsDelegatedAdminAccount: false
prueba5@prueba5.com: {}
prueba7@prueba7.com:
zimbraIsDelegatedAdminAccount: true
zimbraIsDelegatedRootAccount: true
prueba9@prueba9.com: {}
and consequently
Copyshell> cat file.txt
prueba7@prueba7.com
zimbraIsDelegatedAdminAccount: true
zimbraIsDelegatedRootAccount: true
ansible - Take shell cmd stdout_lines and create dict from output - DevOps Stack Exchange
How to save ansible stdout.lines to a file is in list format - Unix & Linux Stack Exchange
linux - Filter line from Ansible stdout_lines result - Stack Overflow
Ansible: Use stdout_lines from registered variable which uses loop in shell module - Stack Overflow
I think you can register the result to a variable, then print with debug.
- name: print to stdout
command: echo "hello"
register: hello
- debug: msg="{{ hello.stdout }}"
- debug: msg="{{ hello.stderr }}"
Instead of stdout I would suggest using stdout_lines. For multiline output this is much nicer, e.g.
- hosts: all
tasks:
- name: Run ls.sh and output "ls /"
script: ls.sh
register: out
- debug: var=out.stdout_lines
gives
TASK: [debug var=out.stdout_lines] ********************************************
ok: [local] => {
"var": {
"out.stdout_lines": [
"total 61",
"lrwxrwxrwx 1 root root 7 Feb 15 2015 bin -> usr/bin",
"drwxr-xr-x 6 root root 1024 Aug 24 22:08 boot",
"drwxr-xr-x 22 root root 3580 Sep 8 18:41 dev",
[...]
"drwxr-xr-x 9 root root 4096 Aug 25 19:14 usr",
"drwxr-xr-x 13 root root 4096 Feb 25 2015 var"
]
}
}
Regarding real time output for debugging purposes there is a closed bug report https://github.com/ansible/ansible/issues/3887#issuecomment-54672569 discussing the reasons why this is not possible and will not be implemented.
content: "{{ all_hosts_list.stdout_lines|join('\n') }}"
This line worked better for me:
content: "{{ output.stdout_lines | join('\n') }}\n"
It adds a final LF which is otherwise omitted.
The join function "concatenates a list into a string" using the character provided in the parameter as the separator between list items. The output first exists as a list, without line terminators; the join() converts the list to a single string with LFs at the end of each former list item. Except for the final \n, which I added above.
Docs: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html
aws cli generates JSON output by default, use this advantage:
---
- hosts: localhost
gather_facts: no
tasks:
- shell: aws sqs list-queues --region eu-west-1
register: sqs_list
- debug:
msg: "{{ (sqs_list.stdout | from_json).QueueUrls | last }}"
Output:
PLAY [localhost] **********************************
TASK [command] ************************************
changed: [localhost]
TASK [debug] **************************************
ok: [localhost] => {
"msg": "https://eu-west-1.queue.amazonaws.com/xxxxx/test"
}
Script:
---
- name: A simple template
hosts: local
connection: local
gather_facts: False
tasks:
- name: list queue
shell: aws sqs list-queues --region us-east-1 --queue-name-prefix test_sqs --query 'QueueUrls[*]' --output text
register: sqs_list
- debug:
msg: "{{ sqs_list.stdout_lines|list }}"
Output:
ok: [localhost] => {
"msg": [
"https://queue.amazonaws.com/xxxxxxxxx/test_sqs-198O8HG46WK1Z"
]
}
You can make use of the --queue-name-prefix parameter to list only queues which is starting with name test_sqs. If there is only one queue with that name, you can use this solution.
Hi everyone
I am running a command to get a username, get very specific account attributes. that part works great. Now i need to get those attributes into variables that I can use in a different portion of the playbook. How would I do that?
Here is what I have so far:
- name: Lookup account
win_shell: get-aduser -Identity {{prompt_win_user_name}} -Properties * |Select-Object cn, gecos, gidNumber, unixHomeDirectory, loginShell, mail, shadowMax, uid, uidNumber
delegate_to: DOMAINCONTROLLER
vars:
ansible_become: yes
ansible_become_method: runas
ansible_become_user: SYSTEMwhen I run the above I get this back:
cn : I get the correct info I need here gecos : I get the correct info I need here gidNumber : I get the correct info I need here unixHomeDirectory : I get the correct info I need here loginShell : I get the correct info I need here mail : I get the correct info I need here shadowMax : I get the correct info I need here uid : I get the correct info I need here uidNumber : I get the correct info I need here
How Do i translate those results back into variables I can feed into a script later on in the process?
Any help would be greatly appreciated
thanks
app
i am trying to compare the output of a script which get the IP of a server with ansible_default_ipv4.address to make sure that the IP of the server is the same
i run ip a command in a script and then call the script module to call it.
this is the script I am calling:
/usr/bin/env bash
a_iplist_ip=$( ip a | grep -w inet | grep -v "lo$" | cut -f1 -d/ | sed "s/inet//g")
echo $a_iplist_ip
then I create a playbook as this:
---
- hosts: all
tasks:
- name: register IP
script: ip.sh
register: command_output
- set_fact:
a_iplist_ip={{ command_output.stdout_lines }}
somehoe the contents of the varilable is not the ip which is what is returned in the script above there are other things in stdout_lines so when I compare to ansible_default_ipv4.address they do not match
this confirms that the two values are not equal altough they should..
- fail:
msg: " {{ a_iplist_ip }} not equal to {{ ansible_default_ipv4.address }}
when: a_iplist_ip != ansible_default_ipv4.address
thanks
Is there a way to do so without creating a particular playbook with debug or any other modules just by adding an option or piping the output to a grep?
I'm quite sure my above proposition in comment fulfills your expectation. The only requirement is to have a tool installed on the controller to parse json so that you can pipe Ansible output result in your shell.
For the below example, I use jq which is widely used and available in most Linux distribution repos.
The trick here is to:
- enable loading callbacks for ad-hoc commands.
- change the stdout callback plugin to use json for ad-hoc commands.
Since you seem to look for a one liner and non "destructive" solution, I used environment variables set directly on the same command line.
Long story short, typing in your shell:
CopyANSIBLE_LOAD_CALLBACK_PLUGINS=1 \
ANSIBLE_STDOUT_CALLBACK=json \
ansible localhost -a "echo toto" | jq -r ".plays[].tasks[].hosts[].stdout"
gives
toto
In my point of view, the in the original question tried approach to gather service statuses should be avoided since that example seems to be an anti-pattern for Ansible. However, there are options to fulfill the requirement for a report.
A simpler solution is either
ansible test -m systemd -a 'name=cntlm enabled=true'
test.example.com | SUCCESS => {
"changed": false,
"enabled": true,
"name": "cntlm",
"status": {
<a lot of output>
}
}
or
Copyansible test -m shell -a 'systemctl status cntlm'
test.example.com | CHANGED | rc=0 >>
● cntlm.service - CNTLM HTTP Accelerator For NTLM Secured Proxies Authenticator
Loaded: loaded (/usr/lib/systemd/system/cntlm.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2022-09-01 09:00:00 CEST; 1 weeks 4 days ago
Main PID: 234567 (cntlm)
CGroup: /system.slice/cntlm.service
└─234567 /usr/sbin/cntlm -c /etc/cntlm.conf -U cntlm -P /run/cntlm/cntlmd.pid
or almost the requested, after enabling callback plugin for ad hoc commands
Copyansible test -m shell -a 'systemctl status cntlm'
PLAY [Ansible Ad-Hoc] **************************************************************************************************
Monday 01 September 2022 09:00:00 +0200 (0:00:00.071) 0:00:00.071 ******
TASK [shell] ***********************************************************************************************************
changed: [test.example.com]
PLAY RECAP *************************************************************************************************************
test.example.com : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Monday 01 September 2022 09:00:00 +0200 (0:00:02.171) 0:00:02.243 ******
===============================================================================
shell ----------------------------------------------------------------------------------------------------------- 2.17s
Playbook run took 0 days, 0 hours, 0 minutes, 2 seconds
Config
Copy[defaults]
bin_ansible_callbacks = True
Further Q&A
- How can I get the output of Ansible ad-hoc command in JSON, CSV or other format?
Finally, If you are now are interested in customizing the output more, you'll probably need to start Developing plugins and creating your own Callback plugin. The source of lib/ansible/plugins/callback/default.py can be a good start.