0

How to write bash script that delays execution of its commands for a few seconds since it was run last time? I mean store somewhere last execution time, calculate diff to current time and then sleep, say 5 seconds, if last run was less than 5 secs away.

Roman Kolesnikov
  • 11,777
  • 11
  • 44
  • 67
  • 2
    `touch somefile` updates the timestamp of `somefile` to the current time. `stat --format=%Y somefile` gives you timestamp of a file as an integer (if you have GNU stat). Those two commands should be all you need, no? (If you need to prevent multiple concurrent invocations, then things get stickier and you start wanting to do locking with `flock` in addition). – Charles Duffy Jan 11 '18 at 22:51
  • 2
    Why do you even want to do this? It smells like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). There may be other solutions, such as: (a) sleep at the end of the script; (b) have the parent process sleep; (c) don't sleep at all; (d) use cron; (e) use watch. – John Kugelman Jan 11 '18 at 23:48
  • I have a problem with docker-compose in jenkins. its a documented bug when building with docker-compose simultaneously causes duplicate container error. so I use this fix to use docker-compose in pipeline – Roman Kolesnikov Jan 12 '18 at 21:56

2 Answers2

2

The first question I would ask myself is, "Do I really need to delay the execution of the script for these commands?" If you can run multiple commands in parallel and then wait for each process to finish with the wait command, that is generally faster and preferable. Have a look at this SO question discussing the difference between wait and sleep

That said, you can do something like this if you really need to wait at least five seconds:

#!/bin/bash
export delay_seconds=5
export start_time=`date +%s`

#Run some commands here...

seconds_since_start=`expr \`date +%s\` - $start_time`

if [ $seconds_since_start -lt $delay_seconds ]; then
    time_remaining=`expr $delay_seconds - $seconds_since_start` 
    echo "Sleeping "$time_remaining" seconds..."
    sleep $time_remaining
else
    echo $seconds_since_start" seconds have already passed since the commands above started.  Continuing..."
fi

echo "Script finished."
terafl0ps
  • 684
  • 5
  • 8
1

In case someone needs it:

timeout=5
timefile=/tmp/dc-time.info
if [[ ! -e $timefile ]]; then
    touch $timefile
fi
old=`stat $timefile --format=%Y`
touch $timefile
new=`stat $timefile --format=%Y`
count=$((timeout-new+old))
if [ $count -gt 0 ]
then
    echo "waiting..."
    sleep $count
fi
Roman Kolesnikov
  • 11,777
  • 11
  • 44
  • 67