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

Arrays 将远程ssh命令的输出存储到循环中的局部变量,arrays,bash,for-loop,ssh,echo,Arrays,Bash,For Loop,Ssh,Echo,我尝试对主机列表运行命令,然后将输出存储在循环中的变量中。我还创建了一个数组来关联ip/主机名,因为我的命令只接受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" S

我尝试对主机列表运行命令,然后将输出存储在循环中的变量中。我还创建了一个数组来关联ip/主机名,因为我的命令只接受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:第20行:10.0.0.1:未找到命令 ./test_array.sh:第20行:数组:错误的数组下标

我可以猜这是一个语法错误,但无法理解。谢谢你的帮助

在这一行中

my_variable_name_$(${array[$($ip)]})_$c= ...
$(${array{…}})
语法是问题所在。实际上,包装数组的
$(…)
正在尝试调用命令。删除
$(
和相应的
。同样,在这一行下面的
echo
语句中

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

$(${array{…}})
语法是问题所在。实际上,包装数组的
$(…)
正在尝试调用命令。删除
$(
和相应的
。同样,在下面的
echo
语句中。

您必须通过
eval
运行此语句,并且为了避免复杂/不可读的语句,我将使用一个临时变量:

vname=my_variable_name_${array[$ip]}_$c
tmp=$($SSH ...)
eval $vname=\$tmp
要查看发生了什么,可以添加

set -x

在语句之前或将其称为
bash-x您的脚本

您必须通过
eval
运行此脚本,为了避免复杂/不可读的语句,我将使用一个临时变量:

vname=my_variable_name_${array[$ip]}_$c
tmp=$($SSH ...)
eval $vname=\$tmp
要查看发生了什么,可以添加

set -x
在语句之前或将其称为
bash-x您的脚本

我会将其重写为

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
  • 不需要将数组键存储在单独的变量中
  • 将命令存储在数组中更健壮()
  • 如果您正在呼叫
    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
我会把它改写成

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
  • 不需要将数组键存储在单独的变量中
  • 将命令存储在数组中更健壮()
  • 如果您正在呼叫
    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

我把它改为:my_variable_name_${array[$($ip)]}_$c=$($SSH“$COMMAND-I$ip | grep-I\“ipv4计数”| awk'{print\$4}')echo my u variable_name_${array[$($ip)]}$c done;做了,但又犯了同样的错误/test_array.sh:第20行:10.0.0.1:找不到命令。/test_array.sh:第20行:数组:错误的数组下标据我所知,它不喜欢将-I$ip作为单独命令的赋值右侧,但它应该是$command的参数。我想看到一个变量名,比如我的变量名,比如我的变量名,10.0.0.1我的变量名,我的变量名,10.0.0.1我的变量名,等等。我把它改成:我的变量名,数组[$($ip)]}c=$($SSH“$COMMAND-I$ip | grep-I\'ipv4计数'”,awk'{print\$4')echo我的变量名,数组[$ip]$$c=$done;做了,但又犯了同样的错误/test_array.sh:第20行:10.0.0.1:找不到命令。/test_array.sh:第20行:数组:错误的数组下标据我所知,它不喜欢将-I$ip作为单独命令的赋值右侧,但它应该是$command的参数。我想看到一个变量名,比如my_variable_name_10.0.0.1_1 my_variable_name_10.0.0.1_2 my_variable_name_10.0.0.1_3等等。除了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+用于'${ip}'中的ip+用于'${channel}中的通道”“++echo host1+suffexe1=host1+suffexe2=1+vname=my_variable\u name\u host1++ssh-t-o ConnectTimeout=10-l username my_script\u host'sudo/path\u to_my_remote\u script-i 10.0.0.1-c1 | grep-i“ipv4计数”\124; awk'''''''''{print$4}”“\”,它被卡在这里,我可以用ctrl+c将其断开,它将在内部循环中连续执行下一个值(3、5和7个值)。我认为它不喜欢SSH命令中的转义序列。您的SSH命令中似乎有一个错位的
(接近末尾)除了bash-x SUF1=
echo${array[$ip]}
SUF2=“$channel”vname=my_variable\u name{SUF1}{SUF2}tmp=$($SSH“$COMMAND-I$ip-c$channel | grep-I\'ipv4计数””)eval$vname\=$tmp done;done+for-ip-in'${ip}+for-c$channel“++echo host1+suffexe1=host1+suffexe2=1+vname=my_variable\u name\u host1++ssh-t-o ConnectTimeout=10-l username my_script\u host'sudo/path\u to_my_remote\u script-i 10.0.0.1-c1 | grep-i“ipv4计数”\124; awk'''''''''{print$4}”“\”,它被卡在这里,我可以用ctrl+c将其断开,它将在内部循环中连续执行下一个值(3、5和7个值)。我认为它不喜欢SSH命令中的转义序列。您的SSH命令中似乎有一个错位的
(接近末尾)非常好,这个解决方案有效解决了我的问题。非常感谢。非常好,这个解决方案有效解决了我的问题。非常感谢。