shell - Two while loops behaving strangely, Bash script -
i'm new bash scripting. have written script me info using ssh bunch of servers. ip address of first set of devices 101 148, , other set 201 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 ]] ip=$base.$sd_counter ssh $ip command1 sd_counter=$(($sd_counter +1)) if [ "$sd_counter"==148 ] while [[ $hd_counter -le $hd_end ]] ip=$base.$hd_counter ssh $ip command2 hd_counter=$(($hd_counter +1)) done fi done > log_sd_hd echo "done!"
but reason command1 executed on 192.168.11.101 first, command2 executed on ip range 192.168.11.201-192.168.11.210 second while loop. after first while loop continues till end. why happening? want first while loop done before second while loop. please point out i'm doing wrong?
@0x1cf's answer provides right pointer:
[ "$sd_counter"==148 ]
doesn't work expected.
specifically: "$sd_counter"==148
, based on bash's string synthesizing rules, expanded single string literal: value of $sd_counter
concatenated literal ==148
, , resulting string literal treated boolean. since non-empty string in boolean context evaluates true
, [ "$sd_counter"==148 ]
evaluates true
due lack of spaces around ==
.
aside that: in bash should use [[ ... ]]
rather [ ... ]
- more robust , provides more features.
also note (as @0x1cf notes too) - if using [ ... ]
or [[ ... ]]
- using arithmetic operators right choice when dealing numbers: -eq
, -ne
, -lt
, -le
, -gt
, or -ge
.
generally, though, using (( ... ))
expressions - arithmetic evaluation - provides more flexibility numbers - see below.
that said, your code can simplified using arithmetic evaluation - (( ... ))
(see section arithmetic evaluation
in man bash
):
it allows use c-style arithmetic , boolean expressions. if combine bash's array variables, code can simplified to:
#!/usr/bin/env bash base=192.168.11 start_indices=( 101 201 ) end_indices=( 148 210 ) commands=( command1 command2 ) numranges=${#start_indices[@]} (( range = 0; range < numranges; ++range )); cmd=${commands[range]} (( i=${start_indices[range]}; i<=${end_indices[range]}; ++i )); ip=$base.$i ssh $ip $cmd done done > log_sd_hd
note:
(( ... ))
expressions differ normal bash assignments , conditionals in you:- need not reference variables
$
- need not double-quote variable references
- you may have spaces around assignment operator (
=
) - you may omit spaces around relational operators:
(( sd_counter==148 ))
work.
- need not reference variables
( string1 ... )
creates array elementsstring1
,...
;${#arrayvar[@]}
returns count of elements of array variablearrayvar
;${arrayvar[ndx]}
returns element (0
-based) indexndx
.- it's better avoid all-uppercase variable names such
base
, may conflict environment variables, convention typically all-uppercase.
Comments
Post a Comment