将远程ssh命令的输出存储到循环中的局部变量

时间:2013-11-25 22:02:09

标签: arrays bash for-loop ssh echo

我尝试为主机列表运行命令,然后将输出存储在循环中的变量中。我还创建了一个关联ip / hostname的数组,因为我的命令只接受IP地址作为参数,但我想在变量名中使用主机名和通道名。我的代码看起来像:

#!/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

当我执行我的脚本时,我收到一条错误消息,如:

./ test_array.sh:line 20:10.0.0.1:找不到命令 ./test_array.sh:line 20:array:bad array subscript

我猜它是语法错误,但无法弄清楚。我感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

我将其重写为

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
  • declare命令可以分配给动态创建的变量名,而无需使用eval
  • 您不需要将数组键存储在单独的变量中
  • 在数组中存储命令更加健壮(ref
  • 如果您正在致电awk,则不需要先使用grep
  • 在我看来,太多的变量实际上会降低可读性

第二个想法,我使用另一个数组来存储输出,使用伪多维密钥:

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

答案 1 :(得分:0)

在这一行

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

$(${array{...}})语法是个问题。基本上,包裹数组的$(...)试图调用命令。移除$(和相应的)。同样在下面的echo声明中。

答案 2 :(得分:0)

你必须通过eval来运行它,为了避免复杂/不可读的语句,我会使用一个临时变量:

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

要查看正在发生的事情,您可以添加

set -x

在陈述之前或称之为bash -x your-script