I have a shell task that gets the defrag configuration, and stores it in a variable, like:
- name: Check if hugepages is disabled
shell: cat /sys/kernel/mm/transparent_hugepage/defrag
register: hugepages_status
changed_when: False
In the following task, I want to evaluate the hugepages_status, to see if the last word in it is "never". How can I read the hugepages_status to evaluate just the last word in the string?
Something like:
- name: Disable hugepages
shell: echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
when: swap_status.stdout != "*never"
You can use is search that will search for the string irrespective of the position. I think this would suffice for this scenario. Let me know in case you are looking to search at the end only.
---
- name: play
hosts: localhost
tasks:
- name: Check if hugepages is disabled
shell: cat /sys/kernel/mm/transparent_hugepage/defrag
register: hugepages_status
- name: display the output
debug:
var: hugepages_status.stdout_lines
when: hugepages_status.stdout is search('never')
Related
I'm running a few tasks in a playbook which runs a bash script and registers its output:
playbook.yml:
- name: Compare FOO to BAZ
shell: . script.sh
register: output
- name: Print the generated output
debug:
msg: "The output is {{ output }}"
- include: Run if BAZ is true
when: output.stdout == "true"
script.sh:
#!/bin/bash
FOO=$(curl example.com/file.txt)
BAR=$(cat file2.txt)
if [ $FOO == $BAR ]; then
export BAZ=true
else
export BAZ=false
fi
What happens is that Ansible registers the output of FOO=$(curl example.com/file.txt) instead of export BAZ.
Is there a way to register BAZ instead of FOO?
I tried running another task that would get the exported value:
- name: Register value of BAZ
shell: echo $BAZ
register: output
But then I realized that every task opens a separate shell on the remote host and doesn't have access to the variables that were exported in previous steps.
Is there any other way to register the right output as a variable?
I've come up with a workaround, but there must be an other way to do this...
I added a line in script.sh and cat the file in a seperate task
script.sh:
...
echo $BAZ > ~/baz.txt
then in the playbook.yml:
- name: Check value of BAZ
shell: cat ~/baz.txt
register: output
This looks a bit like using a hammer to drive a screw... or a screwdriver to plant a nail. Decide if you want to use nails or screws then use the appropriate tool.
Your question misses quite a few details so I hope my answer wont be too far from your requirements. Meanwhile here is an (untested and quite generic) example using ansible to compare your files and run a task based on the result:
- name: compare files and run task (or not...)
hosts: my_group
vars:
reference_url: https://example.com/file.txt
compared_file_path: /path/on/target/to/file2.txt
# Next var will only be defined when the two tasks below have run
file_matches: "{{ reference.content == (compared.content | b64decode) }}"
tasks:
- name: Get reference once for all hosts in play
uri:
url: "{{ reference_url }}"
return_content: true
register: reference
delegate_to: localhost
run_once: true
- name: slurp file to compare from each host in play
slurp:
path: "{{ compared_file_path }}"
register: compared
- name: run a task on each target host if compared is different
debug:
msg: "compared file is different"
when: not file_matches | bool
Just in case you would be doing all this just to check if a file needs to be updated, there's no need to bother: just download the file on the target. It will only be replaced if needed. You can even launch an action at the end of the playbook if (and only if) the file was actually updated on the target server.
- name: Update file from reference if needed
hosts: my_group
vars:
reference_url: https://example.com/file.txt
target_file_path: /path/on/target/to/file2.txt
tasks:
- name: Update file on target if needed and notify handler if changed
get_url:
url: "{{ reference_url }}"
dest: "{{ target_file_path }}"
notify: do_something_if_changed
handlers:
- name: do whatever task is needed if file was updated
debug:
msg: "file was updated: doing some work"
listen: do_something_if_changed
Some references to go further on above concepts:
uri module
get_url module
slurp module
delegating tasks in ansible
registering output of tasks
run_once
handlers
How to enter multi-line command in ansible-console, an Ansible REPL? I'm looking for something like \ at the end of the line in bash.
Regular writing from a playbook
- debug:
msg: "hello"
can be transformed to single line form
$ debug msg='hello'
However is there a way to execute
- debug:
msg: 'hello'
register: result
in ansible-console?
Ansible ad hoc commands are for specific use cases, so ansible-console as well. Therefore such things like registering variables aren't possible.
Whereby it would be possible to have the output in JSON, write it into a file and try to parse it later, a small setup which doesn't require any special environment can be look like
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Show message
debug:
msg: "Hello"
register: message
- name: Show registered message
debug:
msg: "{{ message.stdout }}"
I need to get a shell output to a variable in set_fact in ansible. And this variable is referred in the somewhere in the same playbook but targeting a different set of hosts
But I am not sure how to do that.
This is my playbook:
---
- hosts: kube-master
tasks:
- name: Print the value
become: true
shell: |
echo "hi"
set_fact:
banuka: <value-taken-from-above-shell-command>
- hosts: kube-minions
tasks:
- name: Print the variable
become: true
shell: |
echo {{banuka}}
But I don't know these:
1. How to get the shell command output to the variable in set_fact and refer it somewhere
2. Is it possible to have multiple hosts (as shown in the above playbook)
I would do it the following way:
---
- hosts: master01
tasks:
- name: Print the value
shell: |
echo "hi"
register: somevariablename
- name: set fact
set_fact:
myvar: "{{ somevariablename.stdout }}"
- hosts: kube-minions
tasks:
- name: Print the variable
shell: |
echo "{{ hostvars['master01'].myvar }}"
It's important to understand, that set_fact only set a variable on the host which it's executed. Since you have a group kube-master it could be executed on each. I had the same issue in a playbook with Kubernetes-Masters and i used one of them as a "primary" e.q. master01. Then the echo hi will only be executed on that one.
In the second hostgroup, you must refer to the hostvars of your kube-master host like the master01.
Do you have the need to run over all the hosts in the group kube-master?
Trying to make sure an exact string exists for a when condition, but right now trying to get the function working in a simple playbook, but can't seem to get it to work. Also tried escaping characters too
I have tried different variations and tried switching to " instead of ' and vise-versa
my.conf
JAVA_HOME="/opt/java/hotspot/64_bit/jdk1.8.0_201/"
JAVA_HOME=/opt/java/hotspot/64_bit/jdk1.8.0_201/
JAVA_HOME=/opt/java/hotspot/64_bit/jdk1.8.0_202/
JAVA_HOME="/opt/java/hotspot/64_bit/jdk1.8.0_202/"
SUN_JAVA_HOME=/opt/java/hotspot/64_bit/jdk1.8.0_201/
SUN_JAVA_HOME="/opt/java/hotspot/64_bit/jdk1.8.0_201/"
BAE_JAVA_HOME=/opt/java/hotspot/64_bit/jdk1.8.0_201/
BAE_JAVA_HOME=/opt/java/hotspot/64_bit/jdk1.8.0_202/
BAE_JAVA_HOME="/opt/java/hotspot/64_bit/jdk1.8.0_201/"
BAE_JAVA_HOME="/opt/java/hotspot/64_bit/jdk1.8.0_202/"
playbook
---
- hosts: localhost
tasks:
- name: read the passwd file
shell: cat /tmp/my.conf
changed_when: False
register: user_accts
- name: set regex pattern
set_fact:
regex_pattern: ".*^JAVA_HOME=\"/opt/java/hotspot/64_bit/jdk1.8.0_201/\"$"
- name: a task that only happens if the user exists
when: user_accts.stdout |match('{{regex_pattern}}')
debug: msg="user hillsy exists"
I want to make sure it finds this JAVA_HOME="/opt/java/hotspot/64_bit/jdk1.8.0_201/"
and if I change this line to
JAVA_HOME="/opt/java/hotspot/64_bit/jdk1.8.0_209/"
it doesn't find it
I'm wanting to get that exact string so I don't get the other ones in the example above
If you are looking for that exact string, then you don't need a regular expression
- debug:
msg: it matches
# because an empty list is considered "false", if none of the lines
# are equal, this will not run
when: user_accts.stdout_lines | select('eq', the_string) | list
vars:
the_string: JAVA_HOME="/opt/java/hotspot/64_bit/jdk1.8.0_201/"
I need to execute the action in the playbook, only when a directory is non-empty.
How to check the condition in when:
You can do it like this, Here you should change action from debug to something which you want.
Here we are gathering list of files on that directory(no which you want to perform action)
and using debug we are printing the output of that particular command.
Note: You should change my example of debug with your action you want.
---
- hosts: "localhost"
gather_facts: no
tasks:
- name: "Looking for files"
command: ls /path/to/directory
register: command_output
- name: "Looking for output"
debug:
msg: "{{command_output}}"
when: command_output.stdout != ""