Hi
I am trying to speed up the script by making SSH connections to different machines at same time and get output instead of making connection to system one at a time.
I tried following but for loop does not serve the purpose.
tried using ssh -f but that goes to background and loop through one at time for systems in HOST variable
HOST="eagle snake ladder"
downProcess()
{
for process in `cat /tmp/abc |grep -i $HOSTNAME|awk '{print $1}'`
do
echo "Maint command run on $process on $HOSTNAME"
ssh - f $HOSTNAME "echo "i am in $HOSTNAME";" | tee >> $LOG
sleep 1
done
}
for HOSTNAME in $HOST
do
echo "============ Started bouncing processes on $HOSTNAME at `date` ==========\n" >> $LOG
echo "Keeping the process in to Maintenance and Disabling processes on $HOSTNAME ...\n" >> $LOG
downProcess;
done
run any/all scripts through the shellcheck utility before posting - and address any relevant issues it raises. if not installed install or search for the online version.
I think your ssh line has at least 1 syntax error '- f' should read -f unless i'm mistaken ( ie no space between the - and the f ).
ssh - f $HOSTNAME "echo "i am in $HOSTNAME";" | tee >> $LOG
here's a cleaned up attempt , read/digest/test/check/double-check. I've added a bunch more logging,once you are happy the script works to requirements feel free to remove/add/amend as you feel necessary..
you will need to
uncomment the ssh command line
its assumed no password is being prompted for ...
amend the awk command line to match your input file.
I've used a simple 2 field file (embedded in the script)
to be removed
I've presumed the script will be using the bash shell ....
#!/bin/bash
#
# /tmp/abc - used in this example
#
cat << EOF > /tmp/abc
1234 eagle
2345 ladder
3456 eagle
4567 ladder
5678 snake
7890 xWing
6789 ladder
7890 snake
7890 rogue1
9876 ladder
8765 snake
EOF
downProcess()
{
local thisHOST="${1}"
local logfile="${2}"
for process in $( awk -vhost="${thisHOST}" '$2 == host { print $1}' /tmp/abc )
do
printf "Maint command run on pid i%s on host %s\n" "${process}" "${thisHOST}" | tee -a "${logfile}"
#ssh -f "${thisHOST}" 'echo "USER:$(whoami) logged on $(hostname) its $(date)";' | tee -a "${logfile}"
sleep 1
done
}
HOSTS="eagle snake ladder"
LOGFILE="${PWD}/$$.log"
printf "%s START of processing\n" "$(date)" | tee "${LOGFILE}"
for host in ${HOSTS}
do
printf "\nPROCESSING %s\n" "${host}" | tee -a "${LOGFILE}"
printf "============ Started bouncing processes on %s at %s ==========\n" "${host}" "$(date)" | tee -a "${LOGFILE}"
printf "Keeping the process in to Maintenance and Disabling processes on %s\n" "${host}" | tee -a "${LOGFILE}"
downProcess "${host}" "${LOGFILE}" &
done
printf "\n%s END of processing\n" "$(date)" | tee -a "${LOGFILE}"
I would recommend that you think about generating logins via a Script that basically creates multiple screens and each screen can then establish a SSH connection based on its name
It is dangerous but it might make you more able to handle - say a simple
upgrade because most of the work has already been done - just getting
the ssh to open a connection from the multiple screens that you created.
With the proviso - I got caught - never ever let someone harass you
or distract you .
So once you have the screens up you can run the upgrade.
I had this setup.
NOTE doing upgrades is fun but make sure you down load the needed files PRIOR to the upgrade.
Sometimes you may have to move them to another slightly different spot so that upgrade process can find them
Hi
Perhaps I was not clear in my requirement. Sorry about that.
I have 3 hosts HOST="eagle snake ladder"
And, I am on some jumpbox where all these 3 hosts can be accessible using SSH
say Jumpbox1
Now, I need to make 3 simultaneous connections to $HOST
that is jumpbox1> ssh eagle jumpbox1> ssh snake jumpbox1> ssh ladder
Then execute the same commands on these 3 different hosts and come back to jumpbox1
that is why I was using the function downProcess()
and was thinking of calling that function in for loop
But for is sequential. so I am stuck here on how to fork multiple SSH from jumper to hosts
Thank you @munkeHoller
i can try this to call the function in background
printf "%s START of processing\n" "$(date)" | tee "${LOGFILE}" for host in ${HOSTS} do printf "\nPROCESSING %s\n" "${host}" | tee -a "${LOGFILE}" printf "============ Started bouncing processes on %s at %s ==========\n" "${host}" "$(date)" | tee -a "${LOGFILE}" printf "Keeping the process in to Maintenance and Disabling processes on %s\n" "${host}" | tee -a "${LOGFILE}"
I can see the downProcess function being called in script but the print statement does not print anything from downProcess.
does this mean the function is not being called properly?
#!/bin/bash
if [ `whoami` != "dev" ]; then
echo "\n!!! You need to login as dev user to run this script.!!!\n";
exit 2;
fi
LOGNAME=`basename $0` # Name of the Script
LOGFILE="/tmp/$LOGNAME.log"
# Removing logs older than 5 days
find /tmp/$LOGNAME.log.* -mtime +5 -exec rm {} \;
mv $LOGFILE $LOGFILE.`date +%Y%m%d%H%M`
cat /dev/null >> $LOGFILE
chmod 666 $LOGFILE
ARBHOST="eagle snake"
downProcess()
{
local thisHOST="${1}"
local logfile="${2}"
for process in $( awk -vhost="${thisHOST}" '$2 == host { print $1}' /tmp/processlist.config )
do
printf "Maint command run on pid i%s on host %s\n" "${process}" "${thisHOST}" | tee -a "${logfile}"
#ssh -f "${thisHOST}" 'echo "USER:$(whoami) logged on $(hostname) its $(date)";' | tee -a "${logfile}"
sleep 1
done
}
printf "%s START of processing\n" "$(date)" | tee "${LOGFILE}"
for host in ${ARBHOST}
do
printf "\nPROCESSING %s\n" "${host}" | tee -a "${LOGFILE}"
printf "============ Started bouncing processes on %s at %s ==========\n" "${host}" "$(date)" | tee -a "${LOGFILE}"
printf "Keeping the process in to Maintenance and Disabling processes on %s\n" "${host}" | tee -a "${LOGFILE}"
downProcess "${host}" "${LOGFILE}" &
done
printf "\n%s END of processing\n" "$(date)" | tee -a "${LOGFILE}"
OUTPUT
jumpbox1:/tmp> ./test_bounce
Mon Oct 3 20:17:32 GMT 2022 START of processing
PROCESSING eagle
============ Started bouncing processes on eagle at Mon Oct 3 20:17:32 GMT 2022 ==========
Keeping the process in to Maintenance and Disabling processes on eagle
PROCESSING snake
============ Started bouncing processes on snake at Mon Oct 3 20:17:32 GMT 2022 ==========
Keeping the process in to Maintenance and Disabling processes on snake
Mon Oct 3 20:17:32 GMT 2022 END of processing
I don't see this is being printed; so does that means function is not being called?
printf "Maint command run on pid i%s on host %s\n" "${process}" "${thisHOST}" | tee -a "${logfile}"
I added a printf statement into the downProcess function
added a timestamp and hostname against the printf inside the for process loop , makes it easier to identify log messages as they could be intermingled.
updated code below
downProcess()
{
printf "\n\ndownProcess invoked\n\n"
startedAT="$(date +%Y-%m-%d-%H-%M.%S)"
local thisHOST="${1}"
local logfile="${2}"
for process in $( awk -vhost="${thisHOST}" '$2 == host { print $1}' /tmp/processlist.config )
do
printf "%s-%s-:Maint command run on pid %s on host %s\n" "${thisHOST}" "${startedAT}" "${process}" "${thisHOST}" | tee -a "${logfile}"
ssh -f "${thisHOST}" 'echo "USER:$(whoami) logged on $(hostname) its $(date)";' | tee -a "${logfile}"
sleep 1
done
}
here's what I get when I run your code ( I named the script users.latest)
./users.latest
Mon 3 Oct 23:12:26 BST 2022 START of processing
PROCESSING eagle
============ Started bouncing processes on eagle at Mon 3 Oct 23:12:26 BST 2022 ==========
Keeping the process in to Maintenance and Disabling processes on eagle
downProcess invoked
PROCESSING snake
============ Started bouncing processes on snake at Mon 3 Oct 23:12:26 BST 2022 ==========
Keeping the process in to Maintenance and Disabling processes on snake
downProcess invoked
eagle-2022-10-03-23-12.26-:Maint command run on pid process1 on host eagle
Mon 3 Oct 23:12:26 BST 2022 END of processing
snake-2022-10-03-23-12.26-:Maint command run on pid process1 on host snake
ssh: Could not resolve hostname eagle: No address associated with hostname
ssh: Could not resolve hostname snake: No address associated with hostname
eagle-2022-10-03-23-12.26-:Maint command run on pid process2 on host eagle
snake-2022-10-03-23-12.26-:Maint command run on pid process2 on host snake
ssh: Could not resolve hostname eagle: No address associated with hostname
ssh: Could not resolve hostname snake: No address associated with hostname
eagle-2022-10-03-23-12.26-:Maint command run on pid process3 on host eagle
snake-2022-10-03-23-12.26-:Maint command run on pid process3 on host snake
ssh: Could not resolve hostname snake: No address associated with hostname
ssh: Could not resolve hostname eagle: No address associated with hostname
snake-2022-10-03-23-12.26-:Maint command run on pid process4 on host snake
eagle-2022-10-03-23-12.26-:Maint command run on pid process14 on host eagle
ssh: Could not resolve hostname snake: No address associated with hostname
ssh: Could not resolve hostname eagle: No address associated with hostname
#########################
# now, lets see what's in the logfile
#
cat /tmp/users.latest.log
Mon 3 Oct 23:12:26 BST 2022 START of processing
PROCESSING eagle
============ Started bouncing processes on eagle at Mon 3 Oct 23:12:26 BST 2022 ==========
Keeping the process in to Maintenance and Disabling processes on eagle
PROCESSING snake
============ Started bouncing processes on snake at Mon 3 Oct 23:12:26 BST 2022 ==========
Keeping the process in to Maintenance and Disabling processes on snake
eagle-2022-10-03-23-12.26-:Maint command run on pid process1 on host eagle
Mon 3 Oct 23:12:26 BST 2022 END of processing
snake-2022-10-03-23-12.26-:Maint command run on pid process1 on host snake
eagle-2022-10-03-23-12.26-:Maint command run on pid process2 on host eagle
snake-2022-10-03-23-12.26-:Maint command run on pid process2 on host snake
eagle-2022-10-03-23-12.26-:Maint command run on pid process3 on host eagle
snake-2022-10-03-23-12.26-:Maint command run on pid process3 on host snake
snake-2022-10-03-23-12.26-:Maint command run on pid process4 on host snake
eagle-2022-10-03-23-12.26-:Maint command run on pid process14 on host eagle
Thank you for helping me here, but i am not getting same results as yours.
here is my output using same down process function
Jumpbox1> ./test_bounce
Tue Oct 4 20:53:57 GMT 2022 START of processing
PROCESSING eagle
============ Started bouncing processes on eagle at Tue Oct 4 20:53:57 GMT 2022 ==========
Keeping the process in to Maintenance and Disabling processes on eagle
downProcess invoked
PROCESSING snake
============ Started bouncing processes on snake at Tue Oct 4 20:53:57 GMT 2022 ==========
Keeping the process in to Maintenance and Disabling processes on snake
downProcess invoked
Tue Oct 4 20:53:57 GMT 2022 END of processing
The print statement in for loop is not being executed
CODE
downProcess()
{
printf "\n\ndownProcess invoked\n\n"
startedAT="$(date +%Y-%m-%d-%H-%M.%S)"
local thisHOST="${1}"
local logfile="${2}"
for process in $( awk -vhost="${thisHOST}" '$2 == host { print $1}' /tmp/processlist.config )
do
printf "%s-%s-:Maint command run on pid %s on host %s\n" "${thisHOST}" "${startedAT}" "${process}" "${thisHOST}" | tee -a "${logfile}"
ssh "${thisHOST}" 'echo "USER:$(whoami) logged on $(hostname) its $(date)";' | tee -a "${logfile}"
sleep 1
done
}
printf "%s START of processing\n" "$(date)" | tee "${LOGFILE}"
for host in ${ARBHOST}
do
printf "\nPROCESSING %s\n" "${host}" | tee -a "${LOGFILE}"
printf "============ Started bouncing processes on %s at %s ==========\n" "${host}" "$(date)" | tee -a "${LOGFILE}"
printf "Keeping the process in to Maintenance and Disabling processes on %s\n" "${host}" | tee -a "${LOGFILE}"
downProcess "${host}" "${LOGFILE}" &
done
printf "\n%s END of processing\n" "$(date)" | tee -a "${LOGFILE}"
Just tried manually passing values to variables in the function
the for loop returns nothing in my case because awk returns nothing in my code.
Which of the following works for you?
Least precise, search in the whole line awk '/'${thisHOST}'/ {print $1}' ...
More precise, search in field 2 only awk -v host="${thisHOST}" '$2 ~ host { print $1}' ...
Most precise, the whole field 2 must match awk -v host="${thisHOST}" '$2 == host { print $1}' ...
that line awk '/'${thisHOST}'/ {print $1}' /tmp/processlist.config is not what the for loop operates on in the downProcess function - you need to test against the code that is being executed not something else.
if you get something different then perhaps your field separator is not a tab or space or the file is not standard ascii text (I also tried with file in 'dos' format - (ascii with CRLF terminator and it works)), if the file is UTF-16 (nothing returned if the file is in this format) (or some other character set then I don't see it working).
.... what do the following produce
hmm, if your code works for me but not for you then theres some gremlin somewhere at play.
you said this worked awk '/'${thisHOST}'/ {print $1}' /tmp/processlist.config
.... (but showed no output !!), please run against the file and copy/paste all output - including the command line.
additionally,
cat the file please.
try with a file with only a single entry
try with a command you have tested and returns what you expect (share that please)
you can test the function in isolation , just set variables to suit then invoke .