I'm quite new to Ansible so I'm still in learning curve. I'm looking for a way to retrieve a value from script's variable and use it further along with ansible-playbook command.
Saying I have a script I would like to retrieve $hostname info in target node. The script is run in a playbook. When a $HOSTNAME value returns, how can I pass it to my wrapper script so I can reference it with other list?
The script is as simple as follows:
HOSTNAME=$(hostname)
ECHO "$HOSTNAME"
Assuming you are running a script with ansible in one task, you would register the output:
tasks:
- name: Echo value
command: "echo Hello"
register: command_output
Then in your next task, maybe you want to create a file for the hostname:
- shell: "touch {{ item }} "
with_items:
- "{{ command_output.stdout_lines }}"
That's the basic structure - you don't say what command you want to run, but this should get you started.
Here's a nice tutorial: http://www.mydailytutorials.com/ansible-register-variables/
Related
Is it possible to pass command (with args) as variable in ansible?
For example, I have this playbook:
- name: My playbook
hosts: myhosts
tasks:
- name: Run Service Command
ansible.builtin.command: "docker compose run --rm service {{ cmd }}"
args:
chdir: "{{ PATH_COMPOSE_DIR }}"
And then I try to run it as:
ansible-playbook my-book.yml -e cmd="my-cmd --arg1 --arg2"
But then it just stucks on running it and nothing happens. Don't see any errors, anything.
If I fully define command on ansible task or just use variables on arg values, it works. But would be nice to be able to pass whole command, so playbook could be more versatile.
I am trying to emulate this behavior with Ansible raw command but I could not find any feature that achieve this
ssh user#host.com <<EOF
command
exit
EOF
You are simply sending the script:
command
exit
To the remote host. The <<EOF and EOF parts are parsed by your local shell and aren't part of the command. The equivalent ansible task would be:
- raw: |
command
exit
In most cases (if the remote target is running a semi-standard shell), you won't need the exit either; the script will exit after the last command completes.
You don't need to send a multiline commands via ssh, perhaps you have connected with ssh already with ansible when you set ansible_connection variable, e.g. in your inventory file:
[my_host_group]
host.com
[my_host_group:vars]
ansible_connection=ssh
ansible_become_user=root
ansible_ssh_user=user
Then execute a tasks with bash:
- name: Executing multiline command on host.com under user
ansible.builtin.shell: command
delegate_to: "{{ groups['my_host_group'][0] }}"
become: False
Or just use ansible.builtin.command module instead of ansible.builtin.shell if your command is simple and not multi line.
You don't need an exit at the end of your script either (until you want to change an exit code and return them to ansible). 'Failed when' conditions is your firend:
- name: Executing multiline command on host.com under user
ansible.builtin.shell: command
delegate_to: "{{ groups['my_host_group'][0] }}"
register: your_script_results
ignore_errors: True
become: False
- name: Print an exit code on script error
ansible.builtin.debug:
msg: "Script was failed with {{ your_script_results.rc }} exit code"
when: your_script_results.failed
Is it possible in Ansible to write the startup script with input of arguments?
For example, in Unix, when we run it we can do:
/etc/init.d/SCRIPT start|stop|restart
Is it possible to do it in Ansible so it will read the input of start|stop|restart?
You can pass variables into your playbook at runtime using the -e argument. For example:
ansible-playbook playbook.yml -e mode=start
Given the above command line, inside the playbook, you can examine the mode variable:
- hosts: localhost
tasks:
- name: start something
command: echo do you want to be starting something
when: "mode|default('') == 'start'"
You can use as many -e arguments as you want, and you can include variables from a file rather than including them on the command line. E.g., if you have a file vars.yml, you could run:
ansible-playbook playbook.yml -e #vars.yml
So from one perspective, you would need to have three different tasks, each with a different when statement to handle the three start/stop/restart conditions.
But depending on what you're trying to do, there may be a simpler solution. If you're just trying to call the init script from a task, you could instead do this:
- hosts: localhost
tasks:
- name: start something
command: /etc/init.d/SCRIPT {{ mode }}
I'm trying to follow this solution to add use the shell module and ssh-keyscan to add a key to my known_hosts file of a newly created EC2 instance.
After trying to do this multiple ways as listed on that question I eventually ran just the ssh-keyscan command using the shell module without the append. I am getting no output from this task:
- name: accept new ssh fingerprints
shell: ssh-keyscan -H {{ item.public_ip }}
args:
executable: /bin/bash
with_items: "{{ ec2.instances }}"
register: keyscan
- debug: var=keyscan
Debug here shows nothing in stdout and stdout_lines and nothing in stderr and stderr_lines
Note: I tried running this with the bash as the executable shown after reading that the shell module defaults to /bin/sh which is the dash shell on my Linux Mint VirtualBox. But it's the same regardless.
I have tested the shell command with the following task and I see the proper output in stdout and stdout_lines:
- name: test the shell
shell: echo hello
args:
executable: /bin/bash
register: hello
- debug: var=hello
What is going on here? Running ssh-keyscan in a terminal (not through Ansible) works as expected.
EDIT: Looking at the raw_params output from debug shows ssh-keyscan -H x.x.x.x and copying and pasting this into the terminal works as expected.
The answer is that it doesn't work the first time. While researching another method I stumbled across the retries keyword in ansible that allows a retry of whatever command. I tried this and on attempt number 2 in the retry loop it is working.
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.