trouble executing SSH remote ash script on ESXI Host - bash

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

Related

heredoc failing when piped into ssh

I am trying to do commands via ssh using a heredoc. when I use the 'EOF' style:
result=$(ssh $quiet -T ${G_IPAddressBase}${G_TGP} <<- 'EOF'
set pid=`ps -ef | grep TestPatterns | egrep -v 'grep|tail|vi|csh' | gawk '{print $2}'`
if ( "$pid" != "" ) then
echo "TestPatterns ($pid) terminated"
kill $pid
else
echo "TestPatterns down already"
endif
EOF
)
everything works as excepted because the $ and qrave marks are not expanded out.
But if I want to include local variables and use \ to stop the variable from being resolved, the \ does not stop the $ variable from resolving as expected.
result=$(ssh $quiet -T ${G_IPAddressBase}${G_TGP} <<- EOF
set pid=\`ps -ef | grep $mytaskName | grep '\/bin\/bash' | gawk '{print \$2}'\`
if ( "\$pid" == "" ) then
echo "ERROR: $mytaskName cored"
else
if ( -f "$mytaskLogpath" ) then
set agent1Done=1
else
echo "ERROR: $mytaskName didn't make a report file"
endif
endif
EOF
)
The pid is being set to blank because its looks like this on the remote side:
set pid=`ps -ef | grep TestPatterns | egrep -v 'grep|tail|vi|csh' | gawk '{print }'`
Everything that I have read says this should not be happening. If I cat << EOF > /tmp/command.csh the heredoc to a file the commands match what I expect on the remote box and work as expected.
This script is in bash, but the default shell is tcsh and that's what the remote is running so its not because the csh commands are running in a bash window on the remote login.
Any ideas what I am doing wrong?

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
)

Telnet to one computer from multiple computer

I have scenario where I have list of 100s of server . Want to check whether those all server can reach to specified destination server or not by telneting from all server to that destination server.
I have written a code as below,
#!/bin/bash
#bash to check telnet status.
#set -x;
#
#clear
SetParam() {
export URLFILE="Host_PortFile.txt"
export TIME=`date +%d-%m-%Y_%H.%M.%S`
export port=80
export STATUS_UP=`echo -e "\E[32m[ RUNNING ]\E[0m"`
export STATUS_DOWN=`echo -e "\E[31m[ DOWN ]\E[0m"`
export MAIL_TO="admin(at)techpaste(dot)com"
export SHELL_LOG="`basename $0`.log"
}
Telnet_Status() {
SetParam
cat $URLFILE | while read next
do
server=`echo $next | cut -d : -f1`
port=`echo $next | awk -F":" '{print $2}'`
TELNETCOUNT=`sleep 5 | telnet $server $port | grep -v "Connection refused" | grep "Connected to" | grep -v grep | wc -l`
if [ $TELNETCOUNT -eq 1 ] ; then
echo -e "$TIME : Port $port of URL http://$server:$port/ is \E[32m[ OPEN ]\E[0m";
else
echo -e "$TIME : Port $port of URL http://$server:$port/ is \E[31m[ NOT OPEN ]\E[0m";
echo -e "$TIME : Port $port of URL http://$server:$port/ is NOT OPEN" | mailx -s "Port $port of URL $server:$port/ is DOWN!!!" $MAIL_TO;
fi
done;
}
Main() {
Telnet_Status
}
SetParam
Main | tee -a $SHELL_LOG
My Host_PortFile.txt file looks like,
gmail.com:443
But here, i need to go to individual server and has to run this which consumes more time. Is there any modification I can do so that I can run the script from one machine to read all source server name from text file or any and can check that server can reach the destination server or not? Can anyone suggest on this please?

Bash is redirecting output from command only after script has finished

Context
Got a daft script that checks a process is running on a group of hosts, like a watchdog, as I say it's a daft script so bear in mind it isn't 'perfect' by scripting standards
Problem
I've ran bash -x and can see that the script finishes its first check without actually redirecting the output of the command to the file which is very frustrating, it means each host is actually being evaluated to the last hosts output
Code
#!/bin/bash
FILE='OUTPUT'
for host in $(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {' print $2 ' })
do ssh -n -f $host -i <sshkey> 'ps ax | grep myprocess | wc -l' > $FILE 2> /dev/null
cat $FILE
if grep '1' $FILE ; then
echo "Process is NOT running on $host"
cat $FILE
else
cat $FILE
echo "ALL OK on $host"
fi
cat $FILE
done
Script traceback
++ cat /etc/hosts
++ awk '{ print $2 }'
++ grep 'webserver.[2][1-2][0-2][0-9]'
+ for host in '$(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {'\'' print $2 '\''})'
+ ssh -n -f webserver.2100 -i <omitted> 'ps ax | grep myprocess | wc -l'
+ cat OUTPUT
+ grep 1 OUTPUT
+ cat OUTPUT
+ echo 'ALL OK on webserver.2100'
ALL OK on webserver.2100
+ cat OUTPUT
+ printf 'webserver.2100 checked \n'
webserver.2100 checked
+ for host in '$(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {'\'' print $2 '\''})'
+ ssh -n -f webserver.2101 -i <omitted> 'ps ax | grep myprocess | wc -l'
+ cat OUTPUT
2
+ grep 1 OUTPUT
+ cat OUTPUT
2
+ echo 'ALL OK on webserver.2101'
ALL OK on webserver.2101
+ cat OUTPUT
2
+ printf 'webserver.2101 checked \n'
webserver.2101 checked
Issue
As you can see, it's registering nothing for the first host, then after it is done, it's piping the data into the file, then the second host is being evaluated for the previous hosts data...
I suspect its to do with redirection, but in my eyes this should work, it doesn't so it's frustrating.
I think you're assuming that ps ax | grep myprocess will always return at least one line (the grep process). I'm not sure that's true. I'd rewrite that like this:
awk '/webserver.[2][1-2][0-2][0-9]/ {print $2}' /etc/hosts | while IFS= read -r host; do
output=$( ssh -n -f "$host" -i "$sshkey" 'ps ax | grep "[m]yprocess"' )
if [[ -z "$output" ]]; then
echo "Process is NOT running on $host"
else
echo "ALL OK on $host"
fi
done
This trick ps ax | grep "[m]yprocess" effectively removes the grep process from the ps output:
the string "myprocess" matches the regular expression "[m]yprocess" (that's the running "myprocess" process), but
the string "[m]yprocess" does not match the regular expression "[m]yprocess" (that's the running "grep" process)

Execute command when connected to a specified ip

I want to create a script that execute a command when wlan0 if connected to a specific ip. If connected to a different ip, launch a different command (I have a static ip)
I want to avoid launching this script in public wifi.
I hope you guys understand. English is not my main langage
Run this script in script in system startup
cal()
{
a=$(ip addr | grep "wlan0" | sed '1d' |awk '{print $2}' | sed -e 's/\(.*\)...$/\1/')
echo $a
b=10.98.35.96
if [ $b = $a ]
then
echo same
#give command
kill -9 $$
else
echo notsame
sleep 3
cal
fi
}
cal

Resources