'Looping over IP addresses from a file using bash array

I have a file in which I have given all the IP addresses. The file looks like following:

[asad.javed@tarts16 ~]#cat file.txt
10.171.0.201
10.171.0.202
10.171.0.203
10.171.0.204
10.171.0.205
10.171.0.206
10.171.0.207
10.171.0.208

I have been trying to loop over the IP addresses by doing the following:

launch_sipp () {
        readarray -t sipps < file.txt
        for i in "${!sipps[@]}";do
                ip1=(${sipps[i]})
                echo $ip1
                sip=(${i[@]})
                echo $sip
        done

But when I try to access the array I get only the last IP address which is 10.171.0.208. This is how I am trying to access in the same function launch_sipp():

local sipp=$1
echo $sipp
Ip=(${ip1[*]})
echo $Ip

Currently I have IP addresses in the same script and I have other functions that are using those IPs:

launch_tarts () {
        local tart=$1
        local ip=${ip[tart]}

        echo "    ----  Launching Tart $1  ----  "
        sshpass -p "tart123" ssh -Y -X -L 5900:$ip:5901 tarts@$ip <<EOF1
        export DISPLAY=:1
        gnome-terminal -e "bash -c \"pwd; cd /home/tarts; pwd; ./launch_tarts.sh exec bash\""
        exit
EOF1
}

kill_tarts () {
        local tart=$1
        local ip=${ip[tart]}

        echo "    ----  Killing Tart $1  ----   "
        sshpass -p "tart123"  ssh -tt -o StrictHostKeyChecking=no tarts@$ip <<EOF1
        . ./tartsenvironfile.8.1.1.0
        nohup yes | kill_tarts mcgdrv &
        nohup yes | kill_tarts server &
        pkill -f traf
        pkill -f terminal-server
        exit
EOF1
}

ip[1]=10.171.0.10
ip[2]=10.171.0.11
ip[3]=10.171.0.12
ip[4]=10.171.0.13
ip[5]=10.171.0.14

case $1 in
        kill) function=kill_tarts;;
        launch) function=launch_tarts;;
        *) exit 1;;
esac

shift

for ((tart=1; tart<=$1; tart++)); do
       ($function $tart) &
       ips=(${ip[tart]})
       tarts+=(${tart[@]})
done
wait

How can I use different list of IPs for a function created for different purpose from a file?



Solution 1:[1]

How about using GNU parallel? It's an incredibly powerful wonderful-to-know very popular free linux tool, easy to install.

Firstly, here's a basic parallel tool usage ex.:

$ parallel echo {} :::: list_of_ips.txt 
 # The four colons function as file input syntax.†
10.171.0.202
10.171.0.201
10.171.0.203
10.171.0.204
10.171.0.205
10.171.0.206
10.171.0.207
10.171.0.208

†(Specific to parallel; see parallel usage cheatsheet here]).

But you can replace echo with just about any as complex series of commands as you can imagine / calls to other scripts. parallel loops through the input it receives and performs (in parallel) the same operation on each input.

More specific to your question, you could replace echo simply with a command call to your script

Now you would no longer need to handle any looping through ip's itself, and instead be written designed for just a single IP input. parallel will handle running the program in parallel (you can custom set the number of concurrent jobs with option -j n for any int 'n')? .

?By default parallel sets the number of jobs to the number of vCPUs it automatically determines your machine has available.
$ parallel process_ip.sh :::: list_of_ips.txt

Solution 2:[2]

In pure Bash:

#!/bin/bash
while read ip; do
    echo "$ip"
    # ...
done < file.txt

Or in parallel:

#!/bin/bash
while read ip; do
    (
        sleep "0.$RANDOM" # random execution time
        echo "$ip"
        # ...
    ) &
done < file.txt
wait

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2