I am trying to get env variale JAVA_HOME value of a target node using ansible.
- name: Copy JAVA_HOME location to variable
command: bash -c "echo $JAVA_HOME"
sudo: yes
register: java_loc
When i use, java_loc.stdout value in another task, it is showing blank value. How can i get that env variable and use it in another task?
I need to copy files to JAVA dir which is present in JAVA_HOME.
Ansible logins via SSH using non-login shell. Probably your problem is that you defined the environment variable on $HOME/.bash_profile or some other file that requires login shell, so you need to add the "-l" flag to "/bin/bash":
---
- name: Copy JAVA_HOME location to variable
command: /bin/bash -l -c "echo $JAVA_HOME"
sudo: no
register: java_loc
- name: show debug
debug: var=java_loc
Please, give it a try and let me know,
If your Java is sufficiently recent to have jrunscript, you can obtain the Java Path from your Java installation, avoiding any dependency on your environment. The code below does this, and doesn't fail if there's no jrunscript.
- name: Detemine Java home
command: 'jrunscript -e java.lang.System.out.println(java.lang.System.getProperty(\"java.home\"));'
changed_when: False
ignore_errors: True
register: locate_java_home
- name: Set a variable for Java home
set_fact:
java_home: "{{ (locate_java_home.rc == 0) | ternary(locate_java_home.stdout, '') }}"
The solution is based on the proposal made here.
Related
I am using the built-in shell module, and want to use an environment variable inside the creates arg.
Something like the following:
- name: Run pyenv install of Python 3.10.7
shell:
cmd: |
exec $SHELL
pyenv install 3.10.7
# Is something like this possible?
creates: $PYENV_ROOT/versions/3.10.7
My questions are:
Is something like this possible?
Would it expand the environment variable from the Ansible control node or Ansible target?
Possible and the ansible way of doing this would be
- name: Run pyenv install of Python 3.10.7
shell:
cmd: |
exec "{{ ansible_env.SHELL }}"
pyenv install 3.10.7
creates: "{{ ansible_env.PYENV_ROOT }}/versions/3.10.7"
In this case, the variable will be from the managed node (target). Provided gather_facts is set to true.
To use the values from the control node, use lookup
creates: "{{ lookup('env','PYENV_ROOT') }}/versions/3.10.7"
I can run the script with the command line argument on the linux server it works fine.
for e.g.: ./install.sh -n -I <IP address of the server>
The above command is able to install the script on the server.
When I am trying to do via ansible (version 2.5) playbook using the shell module it gives me an argument error.
- name: Running the script
shell: yes | ./fullinstall
Expect modules has been tried.
--my-arg1=IP address
- shell: "./install.sh -n -I"
args:
chdir: somedir/
creates: somelog.txt
You can look here for examples.
You can also place the install.sh file on the server as a template. Then you can set the variables as desired in Jinja2.
- name: Template install.sh
template:
src: /install.sh.j2
dest: /tmp/install.sh
- shell: "cd /tmp/ ; ./install.sh
Your install.sh.j2 contains:
IP adres: {{ my_ip }}
And set the variable on the command line with:
ansible-playbook -e my_ip="192.168.0.1"
Use command module
- name: run script
command: /path/to/install.sh -n -I {{ ip_addrress }}
playbook
ansible-playbook -e ip_address="192.168.3.9" play.yml
If you want to interactively wanted to enter the IP address, use prompt module.
Im trying to run a shell script on the host machine after copying it over there using ansible. The script has 777 permissions.
Please read the below question as it gives the full scope of the actual issue that we are trying to deal with
Set different ORACLE_HOME and PATH environment variable using Ansible
- name: Run the Script [List]
shell: "/tmp/sqlscript/sql_select.sh {{item}} >> /tmp/sqlscript/output.out"
become: yes
become_method: sudo
become_user: oracle
register: orh
with_items: "{{ factor_dbs.split('\n') }}"
Below is the shell script
#!/bin/bash
source $HOME/bin/gsd_xenv $1 &> /dev/null
sqlplus -s <<EOF
/ as sysdba
set heading off
select d.name||','||i.instance_name||','||i.host_name||';' from v\$database d,v\$instance i;
EOF
Despite escalating the privileges, I observed that the task is not executing unless I add environment variables like below
- name: Run the script [List]
shell: "/tmp/sqlscript/oracle_home.sh {{item}} >> /tmp/sqlscript/orahome.out"
become: yes
become_method: sudo
become_user: oracle
environment:
PATH: "/home/oracle/bin:/usr/orasys/12.1.0.2r10/bin:/usr/bin:/bin:/usr/ucb:/sbin:/usr/sbin:/etc:/usr/local/bin:/oradata/epdmat/goldengate/config/sys"
ORACLE_HOME: "/usr/orasys/12.1.0.2r10"
register: orh
with_items: "{{ factor_dbs.split('\n') }}"
However this playbook needs to be run across different hosts which have different path and oracle_home variables.
My question is, why doest the task run despite escalating the permissions. When I try to run the same script manually by logging into the server and after doing "sudo su oracle", it seems to be running fine.
It depends on where you actually set your environment variables. There is a difference in executing a script when you are logged in at a remote machine, and running a script over ssh as Ansible does (see e.g., Differentiate Interactive login and non-interactive non-login shell). Depending on the type of shell and your system, different bash profiles are loaded.
I would like to set output of a shell command as an environment variable in Ansible.
I did the following to achieve it:
- name: Copy content of config.json into variable
shell: /bin/bash -l -c "cat /storage/config.json"
register: copy_config
tags: something
- name: set config
shell: "echo $TEMP_CONFIG"
environment:
TEMP_CONFIG: "{{copy_config}}"
tags: something
But somehow after the ansible run, when I do run the following command:
echo ${TEMP_CONFIG}
in my terminal it gives an empty result.
Any help would be appreciated.
There are at least two problems:
You should pass copy_config.stdout as a variable
- name: set config
shell: "echo $TEMP_CONFIG"
environment:
TEMP_CONFIG: "{{copy_config.stdout}}"
tags: something
You need to register the results of the above task and then again print the stdout, so:
- name: set config
shell: "echo $TEMP_CONFIG"
environment:
TEMP_CONFIG: "{{copy_config.stdout}}"
tags: something
register: shell_echo
- debug:
var: shell_echo.stdout
You never will be able to pass the variable to a non-related process this way. So unless you registered the results in an rc-file (like ~/.bash_profile which is sourced on interactive login if you use Bash) no other shell process would be able to see the value of TEMP_CONFIG. This is how system works.
- name: Go to the folder
command: chdir=/opt/tools/temp
When I run my playbook, I get:
TASK: [Go to the folder] *****************************
failed: [host] => {"failed": true, "rc": 256}
msg: no command given
Any help is much appreciated.
There's no concept of current directory in Ansible. You can specify current directory for specific task, like you did in your playbook. The only missing part was the actual command to execute. Try this:
- name: Go to the folder and execute command
command: chdir=/opt/tools/temp ls
This question was in the results for when I was trying to figure out why 'shell' was not respecting my chdir entries when I had to revert to Ansible 1.9. So I will be posting my solution.
I had
- name: task name
shell:
cmd: touch foobar
creates: foobar
chdir: /usr/lib/foobar
It worked with Ansible > 2, but for 1.9 I had to change it to.
- name: task name
shell: touch foobar
args:
creates: foobar
chdir: /usr/lib/foobar
Just wanted to share.
If you need a login console (like for bundler), then you have to do the command like this.
command: bash -lc "cd /path/to/folder && bundle install"
You can change into a directory before running a command with ansible with chdir.
Here's an example I just setup:
- name: Run a pipenv install
environment:
LANG: "en_GB.UTF-8"
command: "pipenv install --dev"
args:
chdir: "{{ dir }}/proj"