Execute bash script via ansible playbook - bash

I'm looking to run the following shell script via ansible playbook.
#!/bin/bash
oci compute instance list --lifecycle-state RUNNING --region ca-toronto-1 --compartment-id < compartment OCID> --all | grep display-name -A 0 > hostnames.txt
for line in `cat hostnames.txt`
do
#echo $line
if [[ $line == *","* ]]; then
# hostname=$(echo ${line//"display-name"/} | tr -d '",: ')
hostname=$(echo "$line" | tr -d '",')
echo "$hostname"
ssh -tt "$hostname" "sudo puppet agent -tv && sleep 10"
# break
fi
done
This works just like how i want when i run the shell script but I get a blank output when i run via ansible.
Playbook:
---
- name: puppet agent trigger
gather_facts: false
become_user: true
hosts: all
tasks:
- name: trigger puppet agent
shell: |
oci compute instance list --lifecycle-state RUNNING --region ca-toronto-1 --compartment-id <compartment OCID> --all | grep display-name -A 0 > hostnames.txt
for line in `cat hostnames.txt`
do
if [[ $line == *","* ]]; then
hostname=$(echo "$line" | tr -d '",')
echo "$hostname"
ssh -tt "$hostname" "sudo puppet agent -tv && sleep 10"
fi
done
register: shell_output
- debug:
msg: "{{ shell_output.stdout }}"
Please point me as to what im missing.

According the description of your use case it seems to be recommended to transfer the whole logic of the script into Ansible itself. To do so and in respect to the comment regarding add_host_module, you could use an approach like
- name: Create an instance list
shell:
cmd: oc get nodes --no-headers | cut -d " " -f 1 | tr '\n' "," | rev | cut -c 2- | rev
register: instance_list
changed_when: false
To generate the instance_list I've used an OpenShift cluster as example, because I don't have something like oci compute instance list ... accessible.
- name: Add all hosts from instance_list to the script group
add_host:
name: '{{ item }}'
groups: script
loop: "{{ instance_list }}"
From there you could proceed further to execute your command puppet agent -tv && sleep 10.

Related

Bash execute multiple command to a remote server on EOF

I try from my terminal, to execute on remote server a openstack command to a docker. The purpose is to get the id of openstack project.
when condition is true, I want to get id, but the script below failed to get id. I don't know if I can execute if condition to EOF statement
ret="$(ssh -qT root#server << EOF
docker exec openstack bash -c ". adminrc &&
if [ false ]; then openstack project create p_ops &>/dev/null
else :
fi
id_u=$(openstack user show u_ops | grep " id" | cut -d "|" -f3 | xargs)
openstack role add SwiftOperator --project p_ops --user $id_u
id_p=$(openstack project show p_ops | grep " id" | cut -d "|" -f3|xargs)
echo "$id_p""
EOF
)"
I get the output :
Missing value auth-url required for auth plugin password
Missing value auth-url required for auth plugin password
usage: openstack role add [-h]
[--system <system> | --domain <domain> | --project <project>]
[--user <user> | --group <group>]
[--group-domain <group-domain>]
[--project-domain <project-domain>]
[--user-domain <user-domain>] [--inherited]
[--role-domain <role-domain>]
<role>
openstack role add: error: argument --user: expected one argument
I desired the id of project :
echo $id_p
faafe2044c4235ac648faaceae5d1a3bf2a8f7a8ca8a765f5a9621a5e53d9162
You can avoid the use of nested quotes which are giving you problems.
Instead of the complex sentence:
openstack user show u_ops | grep " id" | cut -d "|" -f3 | xargs
you can just write:
openstack user show -f value -c id
ret=$(ssh -qT root#server << EOF
docker exec openstack bash -c ". adminrc &&
if [ false ]; then openstack project create p_ops &>/dev/null
else :
fi
id_u=$(openstack user show -f value -c id u_ops)
openstack role add SwiftOperator --project p_ops --user $id_u
id_p=$(openstack project show -f value -c id p_ops)
echo $id_p"
EOF
)

ssh when invoked with variables form while loop not working

I am running into an issue where I am comparing two files (alert.txt and env.txt) and based on common value, I am pulling complete line data from env.txt based on matching entry. I am reading these values into while loop and then invoking a function as follows. the ssh call is not working and also the while loop inside start_admin not working
#!/bin/bash
start_admin()
{
ssh -n -f $user#$host "sh -c 'cd $domain; ./script.sh > /dev/null 2>&1'"
while !(netstat -na | grep -E $host:$port|grep -E LISTEN) 2>/dev/null
sleep 30
do
echo "waiting"
done
echo "started"
}
grep -Ff alert.txt env.txt | (while IFS=" " read -r r1 r2 r3 r4 r5
do
user=$r2
host=$r3
domain=$r4
port=$r5
done
start_admin $user $host $domain $port
)
and contents of alert.txt is:
env2
env3
and that of env.txt is :
env1 user1 host1 /app/domain1/ port1
env2 user2 host2 /app/domain2/ port2
env3 user3 host3 /app/domain3/ port3
I could solve this with multiple if else loops, but that is not a desired solution, please guide me in right direction as to what is missing ?
Use join instead of grep here to avoid false positives
Because your while read loop completes before you run start_admin, you only launch it once (done should be AFTER start_admin)
In start_admin, don't use $user, $host and so on, use $1, $2 (or use them but don't pass them as parameters when calling the function)
I'm not sure exactly what you try to achieve, but here is a revised version already.
#!/bin/bash
start_admin()
{
sanitized_domain=${domain//'"'/'\"'}
ssh -n -f "$user#$host" "sh -c 'cd \"$sanitized_domain\"; ./script.sh >/dev/null 2>&1'"
while ! netstat -na | grep -q " $host:$port .*LISTEN"; do
echo waiting
sleep 30
done
echo started
}
join alert.txt env.txt | while IFS=' ' read -r env user host domain port; do
start_admin
done
)

How to pass value to ansible command module

I am new to ansible and trying to write some basic playbook. I need to run a command via command module, but that command needs use a value derived from other command this is what I have:
+++++++++++++++++++++++++++++++++++++++++++
---
- name: Post SentinelOne Agent
hosts: all
tasks:
- name: user sentinel exist
command: /usr/bin/grep sentinelone /etc/passwd
register: user_exist
ignore_errors: yes
- name: Create sentinelone user using existing id, only if the user does not exist
command: "useradd -d /opt/sentinelone/home/ -u `ls -ld /opt/sentinelone/ | awk '{print $3}'`** -f 1 -l -g sentinelone -s /sbin/nologin sentinelone"
when: user_exist.rc == 1
- name: Check again to confirm user exist for copy purpose
command: /usr/bin/grep sentinelone /etc/passwd
register: does_user_exist
ignore_errors: yes
- name: Whitelist sentinelone user ... Copy line from /etc/passwd
command: echo "`cat /etc/passwd | grep -i sentinelone`" >> /etc/crypt/passwd_local
when: does_user_exist.rc == 0
- name: Whitelist sentinelone user ... Copy line from /etc/shadow
command: echo "`cat /etc/shadow | grep -i sentinelone`" >> /etc/crypt/shadow_local
when: does_user_exist.rc == 0
+++++++++++++++++++++++++++++
get error:
for
command: "useradd -d /opt/sentinelone/home/ -u `ls -ld /opt/sentinelone/ | awk '{print $3}'`** -f 1 -l -g sentinelone -s /sbin/nologin sentinelone"
STDERR:
useradd: invalid user ID '`ls'
MSG:
non-zero return code

trouble executing SSH remote ash script on ESXI Host

I have two servers: Linux shell (192.168.1.11) and ESXI host ash shell (192.168.1.12).
Desired outcome:
Local testsuspend.sh scp uploads suspendvm.sh to remote ESXI server and executes on ESXI. When finished testsuspend.sh continues and exits.
Script testsuspend.sh on .11 uploads an ash script (suspendvm.sh) to ESXi host .12, should execute it and wait until it's finished,then finish testsuspend.sh.
On Linux I want to remote execute a script suspendvm.sh from another script testsuspend.sh to suspend all VMs and put ESXI host in maintenance mode.
When I execute the testsuspend.sh on Linux it stops on executing suspendvm.sh via SSH. If I execute the suspend script sustendvm.sh on the ESXI host directly it works.
File after copy on ESXI:
-rwxr-xr-x 1 root root 1260 Apr 16 07:06 suspendvm.sh
Would you have an idea on what I need to do here to get the ssh remote script to execute properly on the ESXi host and the local script to wait until remote is finished?
... So I found that if I run this in the testsuspend.sh it works:
cat suspendVM.sh | ssh -T $user#$host
Why does this work but not the copy and execute?
Local script 192.168.1.11, testsuspend.sh should execute suspenvm.sh remotely:
#!/bin/sh
user="root"
host="192.168.1.120"
scp suspendvm.sh $user#$host:/tmp
echo "copy suspend script"
ssh $user#$host 'sh -s /tmp/suspendvm.sh' &
exit
Remote script 192.168.1.12, suspendvm.sh works when I execute on ESXI host .12):
#!/bin/sh
RUNNING=0
VMS=`vim-cmd vmsvc/getallvms | grep -v Vmid | awk '{print $1}'`
for VM in $VMS ; do
# echo "Probing VM with id: $VM."
PWR=`vim-cmd vmsvc/power.getstate $VM | grep -v "Retrieved runtime info"`
name=`vim-cmd vmsvc/get.config $VM | grep -i "name =" | awk '{print $3}' | head -1 | awk -F'"' '{print $2}'
echo "VM with id $VM has power state $PWR (name = $name)."
if [ "$PWR" == "Powered on" ] ; then
RUNNING=1
echo "Powered on VM with id $VM and name: $name"
echo "Suspending VM with id $VM and name: $name"
vim-cmd vmsvc/power.suspend $VM > /dev/null &
fi
done
while true ; do
if [ $RUNNING -eq 0 ] ; then
echo "Gone..."
break
echo "Powered on VM with id $VM and name: $name"
echo "Suspending VM with id $VM and name: $name"
vim-cmd vmsvc/power.suspend $VM > /dev/null &
fi
done
while true ; do
if [ $RUNNING -eq 0 ] ; then
echo "Gone..."
break
fi
RUNNING=0
for VM in $VMS ; do
PWR=`vim-cmd vmsvc/power.getstate $VM | grep -v "Retrieved runtime info"`
if [ "$PWR" == "Powered on" ] ; then
name=`vim-cmd vmsvc/get.config $VM | grep -i "name =" | awk '{print $3}' | head -1 | awk -F'"' '{$
echo "Waiting for id $VM and name: $name..."
RUNNING=1
fi
done
sleep 1
esxcli system maintenanceMode set --enable true
done
Remote script #2 that should do the same via esxicli, it also works when I execute it on .12 but not via ssh from .11:
#! /bin/ash
#test2
rm -f listid
touch listid
######## Listing the running vms################
esxcli vm process list |grep -v "^\s.*"| grep -v "^$" > list
######## If you want to reuse list for later use #######
####### put the file in a datastore, else it ##########
#######gonna be erease on next reboot ##########
####### Command look like this: ###############
## esxcli vm process list |grep -v "^\s.*"| grep -v "^$" > /vmfs/volumes/tmp/list
########## cleaning the id.s file by keeping only the id
for name in `cat list`;do
########## Dont forget to change the path if #######
########## you choose to put it in a datastore #####
####### put the file in a datastore, else it ##########
#######gonna be erease on next reboot ##########
####### Command look like this: ###############
## esxcli vm process list |grep -v "^\s.*"| grep -v "^$" > /vmfs/volumes/tmp/list
########## cleaning the id.s file by keeping only the id
for name in `cat list`;do
########## Dont forget to change the path if #######
########## you choose to put it in a datastore #####
## Example: for name in `cat /vmfs/volumes/yourDatastore/list`;do
vim-cmd vmsvc/getallvms | grep $name | grep vmx | grep -v "^$" | awk '{print $1}'>> listid
done
for id in `cat listid`;do
###### suspending vms##########
echo "Suspending the running machines"
vim-cmd vmsvc/power.suspend $id
## Example: for name in `cat /vmfs/volumes/yourDatastore/list`;do
vim-cmd vmsvc/getallvms | grep $name | grep vmx | grep -v "^$" | awk '{print $1}'>> listid
done
for id in `cat listid`;do
###### suspending vms##########
echo "Suspending the running machines"
vim-cmd vmsvc/power.suspend $id
done
echo "done."
echo "shutting down the host now.."
#/bin/poweroff
vim-cmd hostsvc/maintenance_mode_enter
#excli system maintenanceMode set --enable true
#done

Ansible: escape quotes and listing users password expiry information

How to escape in shell module quotation?
I've tried as follows:
- name: UList
shell: "cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c \" echo {} ; chage -l {}\""
and
- name: UList
shell: "cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c \' echo {} ; chage -l {}\'"
Where is a mistake?
This playbook worked for me, hope this will be helpful for you too. You can use single quotes' for a command if you have an issue escaping " quote
Either do it this way
'cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c " echo {} ; chage -l {}"'
Or
"cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c ' echo {} ; chage -l {}'"
Both are working i have tested it.
---
- name: Set my hosts variable
hosts: localhost
tasks:
- name: UList
shell: 'cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c " echo {} ; chage -l {}"'
register: result
- name: debug
debug:
msg: "{{result}}"
Or
For the output you are expecting for that you can use
awk -F':' '{ system("echo " $1 " && chage -l " $1) }' /etc/passwd
Command explanation
---
- name: Set my hosts variable
hosts: localhost
tasks:
- name: UList
shell: "awk -F':' '{ system(\"echo \" $1 \" && chage -l \" $1) }' /etc/passwd"
register: result
- name: debug
debug:
msg: "{{result}}"

Resources