How to report unsuccessful commands on remote machines? - bash

For instance, I wrote a simple script to delete all the jar files on remote machines.
## distribute commands to machines
for machine in $machines
do
echo $machine
ssh -o "StrictHostKeyChecking no" $machine "rm /home/ubuntu/test.jar" &
done
I want to know whether all these commands were successful. Is there any convenient way?
Thanks!

Get rid of the & backgrounding the sshes and then you can check their exit status with if or ||.
for machine in $machines; do
echo $machine
if ! ssh -o StrictHostKeyChecking=no $machine rm /home/ubuntu/test.jar; then
echo "didn't work" >&2
fi
done
or
succeeded=true
for machine in $machines; do
echo $machine
ssh -o StrictHostKeyChecking=no $machine rm /home/ubuntu/test.jar || succeeded=false
done
if ! $succeeded; then
echo "one or more removals failed" >&2
fi

Related

How to check connection to a list of servers in bash?

Im trying to check connections for a list of servers. I want to loop through the list, check if a connection works and if yes, do some stuff, if not, echo out a problem message.
My problem is:
the script stops at the first node without echoing the $?.
So, whats wrong with my for-loop?
These vars are included from a config file:
$nodes is a list of server IPs like 1.1.1.1,2.2.2.2,10.10.10.10
$user is one string
for node in $(echo $nodes | sed "s/,/ /g")
do
echo "Checking Node: $node"
ssh -q -o ConnectTimeout=3 $user#$node echo ok
echo $?
if [[ $? != 0 ]]
then
echo "Problem in logging into $node"
else
# do some stuff here
fi
done
EDIT #1:
for node in $(echo $nodes | sed "s/,/ /g")
do
echo "Checking Node: $node"
ssh -q -t -o ConnectTimeout=3 $user#$node "echo ok"
retcode=$?
echo $retcode
if [[ "$retcode" -ne 0 ]]
then
echo "Problem in logging into $node"
else
echo "OK"
fi
done
It is because ssh first asks you to validate The authority of the host and If you accept the authority it will ask for password. That is why your command does not return to shell and waits for input.
If your intention is just validating ssh connection, then you may consider to use
telnet <your_host> <port> < /dev/null
But if your intend is to run some commands you need a trust relationship between hosts. In that case you can use:
Execute this commands:
ssh-keygen -t rsa
then
ssh-copy-id -i root#ip_address
Now you can connect with
ssh <user>#<host>
Furher information
You can add -tto make virtual terminal and add quotes on command:
ssh -q -t -o ConnectTimeout=3 ${user}#${node} "echo ok"
Also use -ne instead of != which is for compare strings
if [[ "$?" -ne 0 ]]
Also echo $? mess the return code. You should use something like:
ssh -q -t -o ConnectTimeout=3 ${user}#${node} "echo ok"
retcode=$?
echo $retcode
if [[ "$retcode" -ne 0 ]]
You can rewrite ssh command like this to avoid problems with ssh host keys
ssh -q -t -o StrictHostKeyChecking=no -o ConnectTimeout=3 ${user}#${node} "echo ok"

How to fix bash script parameters from looping parallel to looping sequencially

I have a bash script that ssh in to different machines in a loop, this script also reboots the machines if there is a reboot=y parameter passed (using jenkins).
Issue -
If reboot = y, it fails to loop the ssh command for each host one by one, then echo "rebooting host" then finally run sh app-services.sh $APP
My goal is - after reboot is done I want it to ping the hosts one by one and if ping returns success, ssh back into the machine and restart the services of the application hosted.
My current script -
#!/bin/bash
IP_S="${HOSTS_STAGE}"
IP_P="${HOSTS_PROD}"
APP="$APPLICATION"
export APP
export host
if [ "${ENVIRONMENT}" == 'stage' ]; then
IP="${IP_S}"
elif [ "${ENVIRONMENT}" == 'prod' ]; then
IP="${IP_P}"
fi
echo "${IP}"
for host in ${IP}; do
echo "########################################"
echo "## Running yum update on ${host}"
echo "########################################"
if [ "${REBOOT}" == 'n' ]; then
ssh -i "${id_rsa}" -o StrictHostKeyChecking=no dvopsadmin#${host} "sudo yum update -y"
echo "## Skipping reboot for ${host}"
else
ssh -i "${id_rsa}" -o StrictHostKeyChecking=no dvopsadmin#${host[#]} "sudo reboot"
echo "## Rebooting ${host}"
ping -w 30 -c 1 ${host}
# This is the other script that restart app services
sh app-services.sh $APP
fi
done

Unable to kill remote processes with ssh

I need to kill remote processes with a shell script as follows:
#!/bin/bash
ip="172.24.63.41"
user="mag"
timeout 10s ssh -q $user#$ip exit
if [ $? -eq 124 ]
then
echo "can not connect to $ip, timeout out."
else
echo "connected, executing commands"
scp a.txt $user#$ip://home/mag
ssh -o ConnectTimeout=10 $user#$ip > /dev/null 2>&1 << remoteCmd
touch b.txt
jobPid=`jps -l | grep jobserver | awk '{print $1}'`
if [ ! $jobPid == "" ]; then
kill -9 $jobPid
fi
exit
remoteCmd
echo "commands executed."
fi
After executed it I found the scp and touch clauses had been executed, but the kill clause had not been executed successful and the process is still there. If I run clauses from "jobPid= ..." to "fi" on remote machine the process can be killed. How to fix it?
I put a script on the remote machine which can find and kill the process, then I ran the script on local machine which execute the script on the remote machine with ssh. The script is as follows:
Local script:
#!/bin/bash
ip="172.24.63.41"
user="mag"
timeout 10s ssh -q $user#$ip exit
if [ $? -eq 124 ]
then
echo "can not connect to $ip, timeout out."
else
echo "connected, executing commands"
ssh -q $user#$ip "/home/mag/local.sh"
echo "commands executed."
fi
remote script:
#!/bin/bash
jobPid=`jps -l | grep jobserver | awk '{print $1}'`
if [ ! $jobPid == "" ]; then
kill -9 $jobPid
fi
Your script needs root access (WHICH IS NEVER A GOOD IDEA). Or make sure your program which is running, is running under your webuser/group

trying to make sense of a bash script

The script is supposed to distribute keys from an ossec server to it's clients
cat /usr/local/bin/dist-ossec-keys.sh
#!/bin/sh
#
for host in chef-production2-doctor-simulator01
do
echo "host is $host"
key=`mktemp`
grep $host /var/ossec/etc/client.keys > $key
echo "key is $key"
scp -i /var/ossec/.ssh/id_rsa -B -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $key ossecd#$host:/var/ossec/etc/client.keys >/dev/null 2>/dev/null
rm $key
ech "done"
done
I ran the script line by line and it's output is
host is chef-production2-doctor-simulator01
key is /tmp/tmp.fAZqvNkJ9f
The bash script is created from this template
cat /var/ossec/etc/client.keys
001 #*#*#*#*#*#*#*#*#*#*#197.221.226 7196c76c568258e2ad836f8e1aa37e0758dee969f560ceb59be76879c3f3412d
002 test-agent 10.128.0.9 e2c9b117f26a202598007dcb4ec64e01f18000f9d820f6b3508a95e5313e6537
what is it supposed to do ?
why is it not working?
The error was in the scp -i /var/ossec/... line
My poor linux knowledge failed to notice the
>/dev/null 2>/dev/null
removing that revealed the real error (which was Permission denied (publickey))

how to check a ssh key is copied to remote server by script

I want use a script like below to check if ssh key in my host is copied to remote server:
#!/usr/bin/sh
ssh -q -o StrictHostKeyChecking=no user#server "ls >/dev/null </dev/null"
if [ $? -eq 0 ] ;then
echo "key copied to remote server"
else
echo "key not copied to remote server"
fi
but it always pending on password input in some case,
user#server's password:
if there any way to terminate this session and return error immediately?
add -o PubkeyAuthentication=yes and -o PasswordAuthentication=no to the ssh command in your script

Resources