Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Tracking time spent during a while loop

Status
Not open for further replies.

landhippy

Programmer
Feb 7, 2003
9
GB
I have a unix script which searches for a specific set of gif files and finshes when all of the files are found. For example, the scripts is called as

find_gifs "andy*.gif" 5

which waits until it finds 5 gif files that match the given criteria, see code below:

#!/bin/sh
#** Ver Who When What
#** --- --- ---- ----
#** 1.00 AP 01-May-2003 Original Version
#**
#** Description
#** -----------
#** This script will search for gif files based on what is passed in the
#** command line. The script will wait until the gif is found before
#** it ends.

# By default we have not found any gifs
found=0

# Set the filename to the first command line parameter
filename=$1
target=$2

if [ -z "$target" ]
then
# By default we will only want to find 1 gif, just in case it is not passed
target=1
fi

# If no command line parameter was given, stop.
if [ -z "$filename" ]
then
echo "No filename specified"
exit 1
fi

while [ $found != $target ]
do
# Look for the gif file. Redirect standard error from the list command to
# nothing otherwise the calling web page source will contain hundreds of
# lines stating that the file can not be found
found=`ls $filename 2>/dev/null | grep -c ".gif"`
done

The problem is that I want to add a fail-safe clause in that means that the while loop will stop if the search has reached a certain amount of time, 5 minutes for example.

The only potential way forward that I can think of is to load the current date/time into a variable and each time the while loop is passed, the current time is compared to the variable.

Does anyone know of an easier way around this problem, or how I would go about hacking the date/time values for comparison.
 
Try using date passed to a variable

$ xx=`date '+%T'`
$ echo $xx
11:59:38

You'll have to cater for when the minute is geater than 55

look at the date man page
 
better still, use the builtin SECONDS


SECEND=$((SECONDS+300))

while [ $found != $target ] && [ $SECONDS -lt $SECEND ]
do
# Look for the gif file. Redirect standard error from the list command to
# nothing otherwise the calling web page source will contain hundreds of
# lines stating that the file can not be found
found=`ls $filename 2>/dev/null | grep -c ".gif"`
done


ART
 
Unfortunately $SECONDS is not available. What shell were you using for that?
 
sorry I forgot to say change the hashline to #!/bin/ksh

ART
 
Here's a C wrapper: this looks like what you need
basically. It's a quick hack, but it works fine for
me with linux 2.4.14 and gcc version 2.95.3 20010315.

Call it like:
progname (num seconds to wait) (full path to scriptfile)

Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

#define perr(s) (printf(&quot;%s\n&quot;, s))
int now(char **);

int main(int argc, char **argv) {
time_t start;
int st, end, calc, curr;
struct tm *mypt;
pid_t pid;

           if (argc < 3) {
               perr(&quot;Insufficient args to program: Need time and scriptname&quot;);
               return -1;
           }      
          
           calc = atoi(argv[1]); 
           time(&start);
           mypt = localtime(&start);
           st = (mypt->tm_min * 60 + mypt->tm_sec);
           end = (st + calc);

           if ( (pid = fork()) == 0) {
                 execve(argv[2],NULL,NULL);
           } else {
                  while ( (curr = now(argv)) < end) {
                        sleep(1);
                  }

                  kill(pid,9);
                  printf(&quot;1\n&quot;);
                  return 0;
           }  
return 0;          
}       
                      
int now(char **args) {
time_t start;
struct tm *mypt;
int calc, st, end;

           calc = atoi(args[1]); 
           time(&start);
           mypt = localtime(&start);
           st = (mypt->tm_min * 60 + mypt->tm_sec);

return st;
}

Sample run with a script like this:
Code:
#!/bin/sh

i=10

   while test $i -lt 30
   do
       i=`expr $i + 1`
       echo &quot;HI at count $i!!!&quot;
       sleep 2
   done

OP:
>tloop 5 &quot;/home/mars/test1.sh&quot;
HI at count 11!!!
HI at count 12!!!
HI at count 13!!!
1
 
Of course it's bugged out.
You need to check for hour turnover,etc..or just use epoch time, but it's another idea at least. ;)


 
Thanks for the replies, in the end I hacked the start date/time. I had to check that the timeout value (in minutes) plus the start minutes did not overlap an hour.

So far it seems to work fine :)

#!/bin/sh
#** Ver Who When What
#** --- --- ---- ----
#** 1.00 AP 01-May-2003 Original Version
#**
#** Description
#** -----------
#** This script will search for gif files based on what is passed in the
#** command line. The script will wait until the gif is found before
#** it ends.

#Fail-safe time in minutes
failSafe=1

# Store the current date and time and then get the minutes and seconds
startDateTime=`date '+%T'`
startMinute=`echo &quot;$startDateTime&quot; | cut -c 4-5`

# When the script should stop
if [ `expr $startMinute + $failSafe` -ge 60 ]
then
# If the minute value is greater or equal to 60 then it has spanned an hour
# so minus 60 away from the minutes to get the correct value
timeToStop=`expr $startMinute + $failSafe - 60`
else
#Otherwise just add the failSafe value to the start minute
timeToStop=`expr $startMinute + $failSafe`
fi

# By default we have not found any gifs
found=0

# Set the filename to the first command line parameter
filename=$1
target=$2

if [ -z &quot;$target&quot; ]
then
# By default we will only want to find 1 gif, just in case it is not passed
target=1
fi

# If no command line parameter was given, stop.
if [ -z &quot;$filename&quot; ]
then
echo &quot;No filename specified&quot;
exit 1
fi

#By default we do not want to stop, if the time limit is reached stop will be
#set to 'YES'
stop='NO'

# Keep looping around and checking until either all files are found or the
# time limit has been reached.
while [ $found -lt $target -a $stop != 'YES' ]
do
# Look for the gif file. Redirect standard error from the list command to
# nothing otherwise the calling web page source will contain hundreds of
# lines stating that the file can not be found
found=`ls $filename 2>/dev/null | grep -c &quot;.gif&quot;`

currentDateTime=`date '+%T'`
currentMinute=`echo &quot;$currentDateTime&quot; | cut -c 4-5`

if [ $currentMinute -ge $timeToStop ]
then
stop='YES'
fi
done

#At this point either all the files have been found or the time limit
#has been reached
 
this worked fine for me:

#!/bin/ksh

USAGE=&quot;\nusage: `basename $0` [filename] [count]\n&quot;

if [ $# -ne 2 ]
then
echo $USAGE
exit 1
fi

filename=$1
typeset -i target=$2 found=0 SECEND TMOUT=20
SECEND=$((SECONDS+TMOUT))

while [ $found -ne $target ] && [ ${SECONDS} -lt $SECEND ]
do
# Look for the gif file. Redirect standard error from the list command to
# nothing otherwise the calling web page source will contain hundreds of
# lines stating that the file can not be found
found=`ls $filename 2>/dev/null | grep -c &quot;.gif&quot;`
done

I reduced the time-out to 20 seconds for the test and I had one file in the current working directory called testxxx.gif
and issued: ksh -vx tloop test*.gif 2

...then watched it iterate 20 times and exit. Of course if you don't have the Korn shell then please ignore me but I haven't come across many Unix systems that don't have it!

ART
 
Realised that mine did not work if the current minute was 57, 58 or 59 and the timeout was 3. The old version was stopped straight away because 58 (start minute) was greater than 1 (stop minute)

Got around that as follows (a bit messy though), I add 60 to the stop and start (if it is less than 60 - timeout)

#!/bin/sh
#** Ver Who When What
#** --- --- ---- ----
#** 1.00 AP 01-May-2003 Original Version
#**
#** Description
#** -----------
#** This script will search for gif files based on what is passed in the
#** command line. The script will wait until the gif is found before
#** it ends.

#Fail-safe time in minutes
failSafe=3

# Store the current date and time and then get the minutes and seconds
startDateTime=`date '+%T'`
startMinute=`echo &quot;$startDateTime&quot; | cut -c 4-5`

# When the script should stop
if [ `expr $startMinute + $failSafe` -ge 60 ]
then
# If the minute value is greater or equal to 60 then it has spanned an hour
# so minus 60 away from the minutes to get the correct value
timeToStop=`expr $startMinute + $failSafe - 60`
else
#Otherwise just add the failSafe value to the start minute
timeToStop=`expr $startMinute + $failSafe`
fi

# By default we have not found any gifs
found=0

# Set the filename to the first command line parameter
filename=$1
target=$2

if [ -z &quot;$target&quot; ]
then
# By default we will only want to find 1 gif, just in case it is not passed
target=1
fi

# If no command line parameter was given, stop.
if [ -z &quot;$filename&quot; ]
then
echo &quot;No filename specified&quot;
exit 1
fi

#By default we do not want to stop, if the time limit is reached stop will be
#set to 'YES'
stop='NO'

# Keep looping around and checking until either all files are found or the
# time limit has been reached.
while [ $found -lt $target -a $stop != 'YES' ]
do
# Look for the gif file. Redirect standard error from the list command to
# nothing otherwise the calling web page source will contain hundreds of
# lines stating that the file can not be found
found=`ls $filename 2>/dev/null | grep -c &quot;.gif&quot;`

currentDateTime=`date '+%T'`
currentMinute=`echo &quot;$currentDateTime&quot; | cut -c 4-5`

#If the start time plus fail safe overlaps an hour
if [ `expr $startMinute + $failSafe` -ge 60 ]
then

#Add 60 to the timetoStop
if [ $timeToStop -le 60 ]
then
timeToStop=`expr $timeToStop + 60`
fi

#Add 60 to the current minute unless the current minute is greater or equal
#to 60-failsafe.
#For example if failsafe is 3, add 60 unless it is 57, 58 and 59
if [ $currentMinute -lt `expr 60 - $failSafe` ]
then
currentMinute=`expr $currentMinute + 60`
fi
fi

# Now we can compare current minute with timetostop
if [ $currentMinute -ge $timeToStop ]
then
stop='YES'
fi
done
#At this point either all the files have been found or the time limit
#has been reached
 
Yeah, I noticed that about the hour turnover.
Probably would be easier to use epoch time.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top