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.
  • ( string1 ... ) creates array elements string1, ...; ${#arrayvar[@]} returns count of elements of array variable arrayvar; ${arrayvar[ndx]} returns element (0-based) index ndx.

  • it's better avoid all-uppercase variable names such base, may conflict environment variables, convention typically all-uppercase.

Comments

Popular posts from this blog

apache - Remove .php and add trailing slash in url using htaccess not loading css -

javascript - jQuery show full size image on click -