2016-10-20 47 views
0

我不清楚我在这里做错了什么,或者是否存在某种类型的bash问题?Bash Pass数组功能

我声明了一些静态sting数组,并交互地构建了另一个字符串值数组,并将其全部传递给bash函数。我在函数本身内部看到数组值的腐败。

add_firewall_rich_rules() { 
    node_ips="${1}" 
    swarm_tcp_ports="${2}" 
    swarm_udp_ports="${3}" 
    echo "in: ${node_ips[@]}" 
    echo "in: ${swarm_tcp_ports[@]}" 
    echo "in: ${swarm_udp_ports[@]}" 
    for ip in "${node_ips[@]}" 
    do 
     for tcp_port in "${swarm_tcp_ports[@]}" 
     do 
       rule="'rule family=\"ipv4\" source address=\"$ip\" port protocol=\"tcp\" port=\"$tcp_port\" accept'" 
       cmd="firewall-cmd --permanent --zone=public --add-rich-rule=$rule" 
       echo "$cmd" 
     done 
     for udp_port in "${swarm_udp_ports[@]}" 
     do 
       rule="'rule family=\"ipv4\" source address=\"$ip\" port protocol=\"udp\" port=\"$udp_port\" accept'" 
       cmd="firewall-cmd --permanent --zone=public --add-rich-rule=$rule" 
       echo "$cmd" 
     done 
    done 
} 

declare -a swarm_tcp_ports=('2377' '7946' '4789' '8500' '4000') 
declare -a swarm_udp_ports=('2377' '7946' '4789') 
declare -a node_ips=() 
echo "init: ${node_ips[@]}" 
echo "init: ${swarm_tcp_ports[@]}" 
echo "init: ${swarm_udp_ports[@]}" 
node_ip="" 
last_node_ip="" 
while read -e -p "Enter ip of additional node in the cluster (hit enter twice to stop adding values): " -i "`echo $node_ip |sed 's/[^.]*$//'`" node_ip; do 
    if [ "$node_ip" == "$last_node_ip" ]; then 
    break 
    fi 
    if [[ $node_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then 
    node_ips=("${node_ips[@]}" $node_ip) 
    else 
    echo "hit return again to stop adding values" 
    fi 
    last_node_ip=$node_ip 
    echo "${swarm_tcp_ports[@]}" 
done 

if [ "${#node_ips[@]}" -gt 0 ]; then 
    echo "out: ${node_ips[@]}" 
    echo "out: ${swarm_tcp_ports[@]}" 
    echo "out: ${swarm_udp_ports[@]}" 
    add_firewall_rich_rules ${node_ips[@]} ${swarm_tcp_ports[@]} ${swarm_udp_ports[@]} 
fi 

从终端:

# ./firewall_add_rich_rule.sh 
init: 
init: 2377 7946 4789 8500 4000 
init: 2377 7946 4789 
Enter ip of additional node in the cluster (hit enter twice to stop adding values): 192.168.1.105 
2377 7946 4789 8500 4000 
Enter ip of additional node in the cluster (hit enter twice to stop adding values): 192.168.1.106 
2377 7946 4789 8500 4000 
Enter ip of additional node in the cluster (hit enter twice to stop adding values): 192.168.1. 
hit return again to stop adding values 
2377 7946 4789 8500 4000 
Enter ip of additional node in the cluster (hit enter twice to stop adding values): 192.168.1. 
out: 192.168.1.105 192.168.1.106 
out: 2377 7946 4789 8500 4000 
out: 2377 7946 4789 
in: 192.168.1.105 192.168.1.106 
in: 192.168.1.106 7946 4789 8500 4000 
in: 2377 7946 4789 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.105" port protocol="tcp" port="192.168.1.106" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.105" port protocol="tcp" port="7946" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.105" port protocol="tcp" port="4789" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.105" port protocol="tcp" port="8500" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.105" port protocol="tcp" port="4000" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.105" port protocol="udp" port="2377" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.105" port protocol="udp" port="7946" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.105" port protocol="udp" port="4789" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.106" port protocol="tcp" port="192.168.1.106" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.106" port protocol="tcp" port="7946" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.106" port protocol="tcp" port="4789" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.106" port protocol="tcp" port="8500" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.106" port protocol="tcp" port="4000" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.106" port protocol="udp" port="2377" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.106" port protocol="udp" port="7946" accept' 
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.106" port protocol="udp" port="4789" accept' 

好像从传递到函数的第一阵列的第一个元素被替换该函数调用后经过下一个阵列的所述第一元件由(和我有时会注意到下一个数组,但这次不是)。

+0

请考虑,在未来,生成[最小,完全,可核查示例](http://stackoverflow.com/help/mcve),其具有以再现问题所需的代码只有最小量。在这种情况下,这可能只是几行,根本不涉及防火墙规则。读者应该可以一目了然地确定问题所在 - 现在,您正在给出当前的输出,但不能解释输出与期望/预期输出的差异,而是使读者能够工作深入了解你的代码的意图。 –

+0

...还有,[这里有一些先前的问题](https://www.google.com/search?q=site%3Astackoverflow.com+bash+pass+arrays+to+function&oq=site%3Aackackoveroverflow .com + bash + pass + arrays + to + function&aqs = chrome..69i57j69i58.5983j0j4&sourceid = chrome&ie = UTF-8)关于将数组传递给函数,对于一个偶然的读者来说,它现在不是显而易见的区别于它们中的任何一个(即为什么它不在核心重复)。 –

+0

...如果当前给出的答案实际上是对您的问题的答案,f/e,那将意味着您重复http://stackoverflow.com/questions/1063347/passing-arrays-as-parameters -in-bash –

回答

0

当您将数组传递给函数时,它将展开值。

arr1=("1" "2" "3") 
arr2=("a" "b" "c") 

someFunc "${arr1[@]}" "${arr2[@]}" 

#same as someFunc "1" "2" "3" "a" "b" "c" "d" 

所以在你的函数,你应该采取的阵列的名称,而不是扩大他们和声明为您的函数中的新数组。

arrayTest(){ 
    declare -a localArr1=("${!1}") 
    declare -a localArr2=("${!2}") 

    //process arrays 
} 

arr1=("1" "2" "3") 
arr2=("a" "b" "c") 

arrayTest "arr1[@]" "arr2[@]" 
+2

尝试'arr1 =(“item one”“item two”“item three”)''查看'$ {arr1 [@]}'的问题,而不是正确的'“$ {arr1 [ @]}“'。 –

+2

...并考虑避免使用'function'关键字,这个关键字与POSIX sh不必要地不兼容,而没有优于符合标准的函数定义语法(这只是'arrayTest(){',而不是'function arrayTest (){')。显然其余的代码在这里是不兼容的,但在鼓励习惯或习惯用法的情况下没有意义,这些习惯或习惯用法使得代码在不补偿优点的情况下不可移植。 –

+1

...对于更新版本的bash(4.3),考虑使用namevars:'local -n localArr1 = $ 1',那里;根据这种用法,对函数内的数组所做的更改将反映在该函数之外,而不仅仅是单向传入。 –