How to make faster loop in multiple directories?

Hello,
I am under Ubuntu 18.04 Bionic.
I have one shell script run.sh (which is out of my topic) to run files under multiple directories and one file to control all processes running under those directories ( control.sh ).
I set a cronjob task to check each of them with two minutes of intervals. When a process is dead or when all processes are dead during ramp-up, each process waits for the completion of previous one. That's okay but due to time consuming process of run.sh
it keeps me waiting. To write separate scripts just dedicated to each folder does not sound logic.
Is there a modern way to do this without entering all directory names ?
Just wish say to script: "implement your code to all subfolders"

control.sh

for A in folder1 folder2 folder3 folder4 folder5 folder6 folder7 folder8 \
folder9 folder10 folder11 folder12 folder13 folder14 folder15 ; do
cd $A
PID=$(cat *.pid)
if ! [ -n "$PID" -a -e /proc/$PID ]; then
/home/boris/public_html/run.sh $A
else
    echo "process exists, exit now!"
sleep 2
fi
cd ../
done

Thanks in advance
Boris

That spec is far from being complete nor clear. Some questions (possibly among others):

  • Does the "time consuming process of run.sh " finish within 8 seconds, so a 2 minute cron does make sense?
  • what does "a process is dead" mean? What "ramp-up"?
  • does that directory list represent the complete subdirectory tree to be operated upon, or should some subdirs be excluded (here: by not mentioning them in the list)?
  • does run.sh create a PID file on entry and delete it on exit? BTW, should one single script "hang", the entire control.sh hangs.
  • why the sleep for two seconds when time is critical?

Please amend / rephrase, drawing a broader (or better: complete) picture.

1 Like

Might I suggest that you should really use pushd and popd rather than cd in your script. If a directory in your list does not exist, your trailing cd .. will change away to somewhere you don't expect and all subsequent changes will fail.

It might be safer with something like:-

for A in folder1 folder2 folder3 folder4 folder5 folder6 folder7 folder8 \
folder9 folder10 folder11 folder12 folder13 folder14 folder15
do
   pushd $A >/dev/null 2>&1
   if [ $? -eq 0 ]
   then
      PID=$(cat *.pid)
      if ! [ -n "$PID" -a -e /proc/$PID ]
      then
         /home/boris/public_html/run.sh $A
      else
          echo "process exists, exit now!"
          sleep 2
      fi
      popd >/dev/null 2>&1
   else
      echo "Failed to change into directory $A"
   fi
done

Just a few thoughts.

Kind regards,
Robin

1 Like

Dear Rudic,
Please find my answers below:

-Each loop takes around 20seconds
-I am trying to indicate "reboot of computer" with "dead process" and "ramp"-up" phrases
-There is no any other subdirectory under that environment
-I have just added some new lines to create pid file for each process.
-Regarding sleep 2 , I have just deleted that line. My bad habits..

Just took into consideration of Robin's and Rudic's comments I have just updated both scripts as follows:

control.sh

dir="/home/boris/public_html"
cd $dir
for A in folder1 folder2 folder3 folder4 folder5 folder6 folder7 folder8 \
folder9 folder10 folder11 folder12 folder13 folder14 folder15
do
   pushd $A >/dev/null 2>&1
   if [ $? -eq 0 ]
   then
if ! ps x |grep -v grep |grep -c $(cat /$dir/$A/*.pid) >/dev/null
then
echo "$A is restarting" >> /var/log/$A_reboot.log
kill $(cat /home/boris/public_html/$A/*.pid)
rm /home/boris/public_html/$A/*
cd $dir
./run.sh $A
else
echo `date "+%d/%m/%y %R $A process was OK"` >> /var/log/testok_$A.log
fi
      popd >/dev/null 2>&1
   else
      echo "Failed to change into directory $A"
   fi
done

run.sh

venc= ........
aenc= ..........
ionice -c 3 nice -n 20 /usr/bin/ffmpeg -re -safe 0 -f concat -i 1.txt \
$venc $aenc /home/boris/public_html/$1/$1.m3u8 &
echo $! > "//home/boris/public_html/$1/$1.pid"

Thanks
Boris