Reputation: 983
I'm new to Bash scripting. I have written a script to help me get some info using ssh from bunch of servers. the IP address of first set of devices are from 101 to 148, and the other set are from 201 to 210.
#!/bin/bash
BASE=192.168.11
SD_START=101
SD_END=148
HD_START=201
HD_END=210
SD_counter=$SD_START
HD_counter=$HD_START
while [[ $SD_counter -le $SD_END ]]
do
ip=$BASE.$SD_counter
ssh $ip command1
SD_counter=$(($SD_counter +1))
if [ "$SD_counter"==148 ]
then
while [[ $HD_counter -le $HD_END ]]
do
ip=$BASE.$HD_counter
ssh $ip command2
HD_counter=$(($HD_counter +1))
done
fi
done > log_SD_HD
echo "Done!"
But for some reason command1 is executed on 192.168.11.101 first, then command2 is executed on ip range 192.168.11.201-192.168.11.210 which is the second while loop. After that the first while loop continues till the end. Why is this happening? I want the first while loop to be done before the second while loop. Could someone please point out what I'm doing wrong?
Upvotes: 0
Views: 127
Reputation: 757
There is no reason to nest the loops from what you showed:
#!/bin/bash
BASE=192.168.11
SD_START=101
SD_END=148
HD_START=201
HD_END=210
SD_counter=$SD_START
HD_counter=$HD_START
while [[ $SD_counter -le $SD_END ]]
do
ip=$BASE.$SD_counter
ssh $ip command1
SD_counter=$(($SD_counter +1))
done> log_SD_HD
while [[ $HD_counter -le $HD_END ]]
do
ip=$BASE.$HD_counter
ssh $ip command2
HD_counter=$(($HD_counter +1))
done>> log_SD_HD
echo "Done!"
Upvotes: 2
Reputation: 439682
@0x1cf's answer provides the right pointer:
[ "$SD_counter"==148 ]
doesn't work as expected.
Specifically: "$SD_counter"==148
, based on bash's string synthesizing rules, is expanded to a single string literal: the value of $SD_counter
is concatenated with literal ==148
, and the resulting string literal is treated as a Boolean.
Since a non-empty string in a Boolean context always evaluates to true
, [ "$SD_counter"==148 ]
always evaluates to true
due to lack of spaces around the ==
.
Aside from that: in bash you should use [[ ... ]]
rather than [ ... ]
- it is more robust and provides more features.
Also note (as @0x1cf notes too) that - if using [ ... ]
or [[ ... ]]
- using the arithmetic operators is the right choice when dealing with numbers: -eq
, -ne
, -lt
, -le
, -gt
, or -ge
.
Generally, though, using (( ... ))
expressions - arithmetic evaluation - provides more flexibility with numbers - see below.
That said, your code can be greatly simplified by using arithmetic evaluation - (( ... ))
(see section ARITHMETIC EVALUATION
in man bash
):
It allows you to use C-style arithmetic and Boolean expressions. If we combine this with bash's array variables, your code can be simplified to:
#!/usr/bin/env bash
BASE=192.168.11
START_INDICES=( 101 201 )
END_INDICES=( 148 210 )
COMMANDS=( command1 command2 )
numRanges=${#START_INDICES[@]}
for (( range = 0; range < numRanges; ++range )); do
cmd=${COMMANDS[range]}
for (( i=${START_INDICES[range]}; i<=${END_INDICES[range]}; ++i )); do
ip=$BASE.$i
ssh $ip $cmd
done
done > log_SD_HD
Note:
(( ... ))
expressions DIFFER from normal bash assignments and conditionals in that you:
$
=
)(( SD_counter==148 ))
DOES work.( string1 ... )
creates an array with elements string1
, ...
; ${#arrayVar[@]}
returns the count of elements of array variable arrayVar
; ${arrayVar[ndx]}
returns the element with (0
-based) index ndx
.
BASE
, as they may conflict with environment variables, which are by convention typically all-uppercase.Upvotes: 2
Reputation: 3266
UPDATE
Hint: You can always use #!/bin/bash -x
to trace and debug your scripts.
Maybe using two while
loop is a good idea, just as V_Maenolis showed. However, to answer your question about what's wrong with your script, try this
Replace
if [ "$SD_counter"==148 ]
with
if [ "$SD_counter" -gt 148 ]
which works for me.
So there are two errors
==
operator, that is to say, using A == B
NOT A==B
SD_counter == 148
is incorrect. Because when SD_counter hits 148, your script will run into the second while loop, and you'll get 147, 201, ..., 210, 148
. Using -gt
instead avoids the problem.Upvotes: 2