Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shell script - loop in batches

I have a sample script like below, where I pass the server names as comma separated stings and execute the functions for each server. Now I need to execute this in batches, e.g. in first batch functions will call with a,b,c,d. Once finished they will take next 4 and call the functions and at last they will call last 2. I can't change the 'servers' variable. Any ides/suggestions.

servers = a,b,c,d,e,f,g,h,i,j
OIFS=$IFS;
IFS=",";
for server in ${servers}
do
 function1 server
done
for server in ${servers}
do
 function2 server
done
for server in ${servers}
do
 function3 server
done
IFS=$OIFS;

Please note that server variable length is not fixed and based on the environment it loads different servers.

like image 458
Pinaki Mukherjee Avatar asked Sep 29 '26 19:09

Pinaki Mukherjee


2 Answers

Read the server list into an array, then use substring expansion (aka "slicing"). You can also store the names of the functions to call in an array, if I (now) understand your concern over the size of the list of servers.

IFS=, read -a s <<< "$servers"

bs=4  # batch size
for ((i=0; i<=${#s[@]}; i+=bs)); do
    function1 "${s[@]:i:bs}"
    function2 "${s[@]:i:bs}"
    function3 "${s[@]:i:bs}"
done
like image 98
chepner Avatar answered Oct 01 '26 17:10

chepner


Looks like a job for GNU Parallel to me. Something like this:

parallel -d ',' -k -j 4 'func1 {1}; func2 {1}; func3 {1}'  <<< $servers

Try it out like this:

parallel -d ',' -k -j 4 'echo {1}; sleep 2'  <<< $servers
a
b
c
d
e
f
g
h
i
j

If they really are functions (rather than shell scripts or executables), remember to export them like this:

func1() {
  echo Doing it for $1
  sleep 2
  echo Done with $1
}

export -f func1
like image 32
Mark Setchell Avatar answered Oct 01 '26 17:10

Mark Setchell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!