Reputation: 23
Just started looking at bash scripts yesterday and wanted to make a script for work where in I ping different addresses on a network and using ssh keys I login and shutdown mikrotiks/junipers/computers in order. I came up with this and it seems to work for the 'mikrotik' array but not for the 'other' elif statement. I'm testing this by just changing an IP address from the MikroTik array to the 'other' array to trigger the elif but it doesn't seem to do anything. Just goes straight to the else statement.
This is one of my first proper bash scripts and assembled this using other examples, stuck here for some reason.
#!/bin/bash
#first array to make the script turn off the nodes in the order I want.
targets=(
192.168.10.10
192.168.10.11
192.168.10.2
192.168.10.1
192.168.10.3
192.168.50.21
192.168.50.3
192.168.50.20
192.168.50.2
192.168.50.1
192.168.50.22
)
mikrotik=(192.168.10.1 192.168.10.2 192.158.50.1 192.168.50.2 192.168.10.5) #Mikrotik addresses
other=(192.168.50.3 192.168.10.3 192.168.10.10 192.168.10.11 192.168.50.21 192.168.50.20 192.168.50.22) #other addresses
for target in "${targets[@]}" #For each index of targets do...
do
ping -c1 $target > /dev/null #ping each ip address
if [[ ($? -eq 0) && (${mikrotik[*]} =~ "$target") ]] #if ping successful and target is within mikrotik array
then
echo "$target mikrotik has replied and will now shutdown"
ssh $target "system shutdown"
echo "..................................."
elif [[ ($? -eq 0) && (${other[*]} =~ "$target") ]] #if ping successful and target within the juniper or computer array
then
echo "$target device has replied and will now shutdown"
ssh $target "shutdown now"
echo "..................................."
else
echo "$target didn't reply moving onto next target"
echo "..................................."
fi
done
Upvotes: 2
Views: 108
Reputation: 141155
$?
contains the last command executed. So you do:
command1
if command2 ... $? ...; then # this command has it's own exit status
# and it's nonzero because the body is not executed!
...
elif command3 ... $? ...; then # the __LAST__ command here is command2
# $? has the exit status of command2, __not__ command1
...
fi
The $?
inside elif
has the exit status of [[
executed in the first if
. Because first if
body was not executed, the [[
exited with nonzero exit status - so $?
in the elif
clause will always be nonzero. Generally, using $?
like doing command; if (($?)); then
is an antipattern - don't use it. Check the exit value of the command instead - if command; then
. You want to check the exit status of ping
, so test it with if
:
if ping -c1 $target > /dev/null; then
# those if's could be refactored too to extract common code
if [[ ${mikrotik[*]} =~ "$target" ]]; then
name=mikrotik
command=(system shutdown)
elif [[ ${other[*]} =~ "$target" ]]; then
name=device
command=(shutdown now)
else
handle error
fi
echo "$target $name has replied and will now shutdown"
ssh "$target" "${command[@]}"
else
echo "$target didn't reply moving onto next target"
fi
echo "..................................."
If you really want to store the exit status of command for later use, save it in a temporary variable right after using it, then use that temporary variable.
ping ...
pingret=$?
if ((pingret == 0)); then something; fi
Upvotes: 3