How to put variable in bash script with ansible playbook - bash

I need a put variable in script with an Ansible playbook. I get the variable from Jenkins 'build with parameter' but I can't put a " tag " variable in my script. How can I do that?
This is my script:
export JAVA_HOME=/home/asd/products/app/java8
tag=$(tag)
hzpid=$(ps aux |grep /home/asd/products/app/hzcluster/ |grep -v grep | awk '{print $2}' | sed -r 's/%/ /g')
echo $hzpid
if [[ -z $hzpid ]]; then
echo "no running applications"
else
kill -9 $hzpid && echo "running process terminated."
fi
nohup $JAVA_HOME/bin/java -Dspring.profiles.active=dxl-dev -jar /home/asd/products/app/hzcluster/new/hzcluster-$tag-SNAPSHOT.jar > $LOG_DIR/hzcluster.log &
exit 0
This is my ansible-playbook:
- hosts: '{{ hosts }}'
gather_facts: no
tasks:
- name: Run new hzcluster.jar
shell: sh '{{ sh_file }}'start-hzcluster2.sh '{{ tag }}'

In your shell script change from tag=$(tag) to tag=$1
Playbook:
- hosts: '{{ hosts }}'
gather_facts: no
tasks:
- name: Run new hzcluster.jar
shell: sh '{{ sh_file }}'start-hzcluster2.sh '{{ tag }}'

Related

Why does Ansible think this shell command has a non-zero return code?

I have this recipe:
- name: Kill usr/bin/perl -w /usr/share/debconf/frontend
shell: "{{ item }}"
with_items:
- 'pkill -9 -f debconf/frontend || echo'
changed_when: false # Don't report changed state
When I run this on the command line, it returns a 0 exit code thanks to || echo:
~$ pkill -9 -f debconf/frontend || echo
~$ $?
0
However running in Ansible it shows this:
failed: [testhost1] (item=pkill -9 -f debconf/frontend || echo) => {"ansible_loop_var": "item", "changed": false, "cmd": "pkill -9 -f debconf/frontend || echo", "delta": "0:00:00.132296", "end": "2023-01-13 10:34:11.098765", "item": "sudo pkill -9 -f debconf/frontend || echo", "msg": "non-zero return code", "rc": -9, "start": "2023-01-13 10:34:10.966469", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
Any ideas what I'm doing wrong?
Starting a test process via
perl -MPOSIX -e '$0="test"; pause' &
a minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Shell task
shell:
cmd: "{{ item }}"
with_items:
- 'pkill -9 -f test || echo'
register: result
- name: Show result
debug:
msg: "{{ result }}"
reproduce the issue. Using instead
with_items:
- 'pkill -9 -f test'
or
with_items:
- 'kill -9 $(pgrep test) || echo'
will execute without an error.
Links
How can I start a process with any name which does nothing?
How to kill a running process using Ansible?
Similar Q&A
with the same error message
Ansible: How force kill process ...?
Further Reading
Since it is recommended to use Ansible modules instead of shell commands if possible
pids module – Retrieves process IDs list if the process is running otherwise return empty list
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Get Process ID (PID)
pids:
name: test
register: PID
- name: Show PID
debug:
msg: "{{ PID.pids | first }}"
- name: Shell task
shell:
cmd: "kill -9 {{ PID.pids | first }}"
register: result
- name: Show result
debug:
msg: "{{ result }}"
Ah, this is because running pkill from inside of Ansible causes it to kill itself (bug in pkill?)
In any case, a workaround is to do this:
with_items:
- 'if pgrep -f "debconf/frontend" | grep -v $$; then sudo pkill -9 -f "debconf/frontend"; fi'

Ansible | Variable declaration to bash script

I have a bash script under files which needs a variable to get passed from default\main1.yml. How can I declare the same?
roles
config
defaults
main1.yml
files
script.sh
tasks
main2.yml
defaults\main1.yml
log_group_name: "{{ lookup('env','LOG_GROUP') }}"
script.sh
for NAME in $(ls -1p /home/ec2-user/ |grep -v "^_" | grep -v "/$" |cut -d. -f1);
do
if ! grep $NAME /etc/awslogs/awslogs.conf;
then
sudo tee -a /etc/awslogs/awslogs.conf << END
[$DAGNAME]
datetime_format = %b %d %H:%M:%S
file = /var/log/airflow/$NAME/*/*/*.log
buffer_duration = 5000
log_stream_name = $NAME
initial_position = start_of_file
log_group_name = ${log_group_name}
END
fi
done
sudo service awslogsd start
sudo systemctl enable awslogsd
task/cloud.yml
---
- name: 'Cloud | AWSlogs.conf file'
when: inventory_hostname == 'master'
script: ../files/cloud.sh
- name: 'Cloud | AWSlogs.conf file'
when: inventory_hostname == 'worker_1'
script: ../files/cloud.sh
ansible command to execute the play:- deploy.py
execute(['sudo', '-E', 'ansible-playbook', 'ansible/plays/deploy.yml', '-i', 'hosts.yml'],
stdout=sys.stdout, stderr=sys.stderr, env=aug_env)
See if this works -
- hosts: localhost
tasks:
- shell: "script.sh {{ log_group_name }}"
You need to set the variable within the execution environment of the script, but it clearly already exists since you're pulling it out of the ENV so you don't even need to do that. If you did, you could install the script via the Ansible template module and execute the script that way.
https://docs.ansible.com/ansible/latest/user_guide/playbooks_environment.html
Simply use the script's parameter
script.sh
log_group_name=$1
...
and run the script with the parameter
roles/config/tasks/main2.yml
- command: "{{ role_path }}/files/script.sh {{ log_group_name }}"
You probably know, but just to be sure. This will work with the "localhost" only. In other cases, the script must be copied to the "remote hosts" first and the path to the script must be changed.

how to do a successful exit from the playbook task

I have a playbook which is repeating one task, shell is invoked from ansible task, but it does not exit successful on completion of task and repeating the shell instructions again.
Playbook:
---
hosts: dev-servers
tasks:
- name: clean up directoty
shell: rm -rf /opt/data/latest/*
- name: copy the file
copy: src=/home/data/metadata.zip dest=/opt/data
- name: Change directoty
shell: cd /opt/data
- name: copy the file
copy: src=/root/Run_Build.sh dest=/opt/deployment_scripts
- name: permission
shell: chmod +x /opt/deployment_scripts/Run_Build.sh
- name: deploy
command: sh /opt/deployment_scripts/Run_Build.sh
run_once: true
register: result
- debug: msg="{{ result.stdout }}"
- debug: msg="{{ result.stderr }}"
Run_Build.sh:
#!/bin/bash
Jboss_logs=/opt/jboss/jboss-eap-6.4/standalone/log/server.log
for i in {1..100}; do
sleep 10
if [ -f $Jboss_logs/server.log ]; then
if grep -e 'Deployed "deploy.war"' $Jboss_logs/server.log ; then
echo "Code successfully deployed"
exit 0
else
echo "*****************************************************************************"
echo " JBOSS is still loading deployment - please be patient .... Loading again in 10 sec"
echo "*****************************************************************************"
fi
else
echo "server log file has not been created yet, please wait for sometime."
fi
done

Write to file specified by user from command line argument - Ansible

I am trying to write a line to a file using lineinfile.
The name of the file is to be passed to the playbook at run time by the user as a command line argument.
Here is what the task looks like:
# Check for timezone.
- name: check timezone
tags: timezoneCheck
register: timezoneCheckOut
shell: timedatectl | grep -i "Time Zone" | awk --field-separator=":" '{print $2}' | awk --field-separator=" " '{print $1}'
- lineinfile:
path: {{ output }}
line: "Did not find { DesiredTimeZone }"
create: True
state: present
insertafter: EOF
when: timezoneCheckOut.stdout != DesiredTimezone
- debug: var=timezoneCheckOut.stdout
My questions are:
1. How do I specify the command line argument to be the destination file to write to (path)?
2. How do I append the argument DesiredTimeZone (specified in an external variables file) to the line argument?
My following answer might not be your solutions.
how to specify the command argument for output variable.
ansible-playbook yourplaybook.yml -e output=/path/to/outputfile
how to include DesiredTimeZone variable from external file.
vars_files:
- external.yml
full playbook.yml for testing on local:
yourplaybook.yml
- name: For testing
hosts: localhost
vars_files:
- external.yml
tasks:
- name: check timezone
tags: timezoneCheck
register: timezoneCheckOut
shell: timedatectl | grep -i "Time Zone" | awk -F":" '{print $2}' | awk --field-separator=" " '{print $1}'
- debug: var=timezoneCheckOut.stdout
- lineinfile:
path: "{{ output }}"
line: "Did not find {{ DesiredTimeZone }}"
create: True
state: present
insertafter: EOF
when: timezoneCheckOut.stdout != DesiredTimeZone
external.yml (place the same level with yourplaybook.yml)
---
DesiredTimeZone: "Asia/Tokyo"
With Ansible you should define the desired state. Period.
The correct way of doing this is to just use timezone module:
- name: set timezone
timezone:
name: "{{ DesiredTimeZone }}"
No need to jump through the hoops with shell, register, compare, print...
If you want to put system into the desired state, just run playbook:
ansible-playbook -e DesiredTimeZone=Asia/Tokyo timezone_playbook.yml
Ansible will ensure that all hosts in question will have the DesiredTimeZone.
If you just want to check if you system comply to desired state, use --check switch:
ansible-playbook -e DesiredTimeZone=Asia/Tokyo --check timezone_playbook.yml
In this case Ansible will just print to the log what should be changed in the current state to become desired state and don't make any actual changes.

ansible overwrite variable depending on result

I am running several shell commands in an ansible playbook that may or may not modify a configuration file.
One of the items in the playbook is to restart the service. But I only want to do this if a variable is set.
I am planning on registering a result in each of the shell tasks, but I do not want to overwrite the variable if it is already set to 'restart_needed' or something like that.
The idea is the restart should be the last thing to go, and if any of the commands set the restart variable, it will go, and if none of them did, the service will not be restarted. Here is an example of what I have so far...
tasks:
- name: Make a backup copy of file
copy: src={{ file_path }} dest={{ file_path }}.{{ date }} remote_src=true owner=root group=root mode=644 backup=yes
- name: get list of items
shell: |
grep <file>
register: result
- name: output will be 'restart_needed'
shell: |
NUM=14"s"; if [ "${NUM}" != "s" ]; then sed -i "${NUM}/no/yes/g" {{ file_path }}; echo "restart_needed"; else echo "nothing_changed" ; fi
with_items: "{{ result.stdout_lines }}"
register: output
- name: output will be 'nothing_changed'
shell: |
NUM="s"; if [ "${NUM}" != "s" ]; then sed -i "${NUM}/no/yes/g" {{ file_path }}; echo "restart_needed"; else echo "nothing_changed" ;; fi
with_items: "{{ result.stdout_lines }}"
register: output
- name: Restart service
service: name=myservice enabled=yes state=restarted
In the above example, the variable output will be set to restart_needed after the first task but then will be changed to 'nothing_changed' in the second task.
I want to keep the variable at 'restart_needed' if it is already there and then kick off the restart service task only if the variable is set to restart_needed.
Thanks!
For triggering restarts, you have two options: the when statement or handlers.
When statement example:
tasks:
- name: check if string "foo" exists in somefile
shell: grep -q foo somefile
register: result
- name: restart service
service:
name: myservice
enabled: yes
state: restarted
when: result.rc == 0
Handlers example:
tasks:
- name: check if string "foo" exists in somefile
shell: grep -q foo somefile
register: result
changed_when: "result.rc == 0"
notify: restart service
handlers:
- name: restart service
service:
name: myservice
enabled: yes
state: restarted

Resources