1

I try to run a command for a list of hosts and then store the output in a variable in a loop. I also created an array to associate ip/hostname as my command will only accept IP address as an argument but I want to use hostname and channel name in variable name. My code looks something like:

#!/bin/bash
IP="10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.5"
CHANNEL="1 2 3 " 
USERNAME="username" 
SCRIPT_HOST="myscript_host" 
HOME_DIR="/home/myuser" 
SCRIPT_DIR=$HOME_DIR/scripts 
COMMAND="sudo /path_to_my_remote_script" 
SSH="ssh -t -o ConnectTimeout=10 -l $USERNAME"

declare -A array
array[10.0.0.1]="host1"
array[10.0.0.2]="host2"
array[10.0.0.3]="host3"
array[10.0.0.4]="host4"
array[10.0.0.5]="host5"

for ip in ${IP} ; do
for channel in ${CHANNEL} ; do

my_variable_name_$(${array[$($ip)]})_$c=$($SSH "$COMMAND -i $ip |grep -i \"ipv4 count\"|awk {print \$4}'") 

echo my_variable_name_$(${array[$($ip)]})_$c
done;done

When I execute my script I receive an error message like:

./test_array.sh: line 20: 10.0.0.1: command not found ./test_array.sh: line 20: array: bad array subscript

I can guess it's a syntax error but can't figure out. I appreciate any help.

2
  • I changed it to: my_variable_name_${array[$($ip)]}_$c=$($SSH "$COMMAND -i $ip | grep -i \"ipv4 count\" | awk ' {print \$4}'") echo my_variable_name_${array[$($ip)]}_$c done; done But again same error. ./test_array.sh: line 20: 10.0.0.1: command not found ./test_array.sh: line 20: array: bad array subscript Commented Nov 25, 2013 at 22:33
  • As much as I understand, it didn't like either right side of the assignment it takes -i $ip as a separate command but it should be a parameter of $COMMAND command. I want to see a variable name such as my_variable_name_10.0.0.1_1 my_variable_name_10.0.0.1_2 my_variable_name_10.0.0.1_3 and so on. Commented Nov 25, 2013 at 22:34

3 Answers 3

1

I'd rewrite that as

declare -A array
array[10.0.0.1]="host1"
array[10.0.0.2]="host2"
array[10.0.0.3]="host3"
array[10.0.0.4]="host4"
array[10.0.0.5]="host5"

channels="1 2 3"
script=/path_to_my_remote_script
cmd=(ssh -t -o ConnectTimeout=10 -l username myscript_host)

for ip in "${!array[@]}" ; do
    for channel in $channels ; do
        varname=my_variable_name_${array[$ip]}_$channel
        echo $varname

        remote_script="sudo $script -i $ip | awk -v IGNORECASE=1 '/ipv4 count/ {print \$4}'"
        out=$( "${cmd[@]}" "$remote_script" )

        declare "$varname=$out"
    done
done
  • the declare command can assign to dynamically created variable names without having to use eval
  • you don't need to store the array keys in a separate variable
  • storing commands in arrays is more robust (ref)
  • if you're calling awk, you don't need to use grep first
  • in my opinion, too many variables can actually reduce readability

On second thought, I'd use another array to store the output, using a pseudo-multi-dimensional key:

declare -A my_variable_name
for ip in "${!array[@]}" ; do
    for channel in $channels ; do
        remote_script="sudo $script -i $ip | awk -v IGNORECASE=1 '/ipv4 count/ {print \$4}'"
        my_variable_name[$ip,$channel]=$( "${cmd[@]}" "$remote_script" )
    done
done
Sign up to request clarification or add additional context in comments.

Comments

0

In this line

my_variable_name_$(${array[$($ip)]})_$c= ...

the $(${array{...}}) syntax is the issue. Essentially the $(...) wrapping the array is trying to call a command. Remove the $( and corresponding ). Likewise in the echo statement below that.

Comments

0

You have to run this through eval and to avoid complicated/unreadable statements I would use a temporary variable:

vname=my_variable_name_${array[$ip]}_$c
tmp=$($SSH ...)
eval $vname=\$tmp

To see what's going on, you can add a

set -x

before the statements or call it as bash -x your-script

3 Comments

I added some more lines to simplify debugging besides bash -x SUF1=echo ${array[$ip]} SUF2="$channel" vname=my_variable_name_${SUF1}_${SUF2} tmp=$( $SSH "$COMMAND -i $ip -c $channel |grep -i \"ipv4 count\" |awk '{print \$4}'" ) eval $vname=\$tmp done;done
+ for ip in '${IP}' + for channel in '${CHANNEL}' ++ echo host1 + SUFFIXE1=host1 + SUFFIXE2=1 + vname=my_variable_name_host1_1 ++ ssh -t -o ConnectTimeout=10 -l username my_script_host 'sudo /path_to_my_remote_script -i 10.0.0.1 -c 1 | grep -i "ipv4 count" | awk '\''{print $4}'\''' And it is stuck here, and I can break it with ctrl+c and it will execute next value in inner loop consecutively for 3,5, and 7 values. I think it didn't like somehow escaping sequence in SSH command.
there seems to be a misplaced ' in your ssh command (nearly at the end)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.