Asad Javed
Asad Javed

Reputation: 57

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?

Upvotes: 2

Views: 2298

Answers (2)

John Collins
John Collins

Reputation: 2951

How about using GNU parallel? It's a wickedly powerful, wonderful-to-know, quite popular free Linux tool – very easy and worth the time to install.

Here's a basic example demonstrating the GNU parallel functionality:

$ parallel echo {} :::: list_of_ips.txt 
# NOTE:            ^ These 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

†(See parallel usage cheatsheet here for more GNU parallel command examples.)

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

Now, more specific to your question, you could simply replace echo (above) with a command call to your script:

$ parallel process_ip.sh :::: list_of_ips.txt

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 CPUs it automatically determines your machine has available.)

Upvotes: 4

Piotr Henryk Dabrowski
Piotr Henryk Dabrowski

Reputation: 901

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

Upvotes: 1

Related Questions