Peter Doyle
Peter Doyle

Reputation: 41

Bash Pass Arrays to Function

I am unclear what I am doing wrong here or is there some type of bash issue?

I am declaring some static sting arrays and interactively building up another array of string values, all to be passed to a bash function. I get corruption of the array values it seems inside the function itself.

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

From the Terminal:

# ./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'

It seems like the first element from the first array passed into the function is replacing the first element of the next array passed after the function call is made (and i have noticed sometimes the next array as well but not this time).

Upvotes: 0

Views: 264

Answers (1)

OrangesV
OrangesV

Reputation: 322

When you pass your arrays to the function, it expands the values.

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

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

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

So in your function you should take the name of the arrays rather than expanding them and declaring them as a new array inside your functions.

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

    //process arrays
}

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

arrayTest "arr1[@]" "arr2[@]"

Upvotes: 2

Related Questions