How to run a Linux script every few seconds under cron

From Computer Tyme Support Wiki

(Difference between revisions)
Jump to: navigation, search
(Precise Cron with microsecond resolution)
(Precise Cron with microsecond resolution)
Line 97: Line 97:
Kind of amazing that you can do all this in less than 50 lines of code.
Kind of amazing that you can do all this in less than 50 lines of code.
 +
 +
=== Monit Script to make sure it keeps running ===
 +
 +
<pre>
 +
check directory cron-ms path /var/run/cron-ms
 +
if timestamp > 1 minute then start
 +
 +
start program = "/etc/init.d/cron-ms start"
 +
</pre>
== Companion Program with 1 minute resolution ==
== Companion Program with 1 minute resolution ==

Revision as of 15:00, 4 March 2014

Contents

Overview

Did you ever want to run a program every few seconds, or even fractions of a second, under a linux, unix, bsd or osx cron script? Here's an elegant script that does just that.

Features:

  • Run once per minute under cron
  • Launches multiple programs in parallel
  • Multiple time periods supported simultaneously just by the directory name.
  • It just works
  • Simple, elegant, free

Even though this software is free if you find it really useful and you want to reward/encourage me you can email me an Amazon Gift Certificate to marc@perkel.com.

Precise Cron with microsecond resolution

The existence of the directory of the number of loops per minute creates the schedule. This version supports microsecond resolution assuming your computer can handle it. The number of executions per minute does not have to to evenly divisible by 60 nor is it limited to 60 I have tested it to 6000 and it works.

This version can be installed in the /etc/init.d directory and run as a service.

#! /bin/sh

# chkconfig: 2345 91 61
# description: This program is used to run all programs in a directory in parallel every X times per minute. \
#              Think of this program as cron with microseconds resolution.

# Microsecond Cron
# Usage: cron-ms start
# Copyright 2014 by Marc Perkel
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron"
# Free to use with attribution

# The scheduling is done by creating directories with the number of"
# executions per minute as part of the directory name."

# Examples:
#   /etc/cron-ms/7      # Executes everything in that directory  7 times a minute
#   /etc/cron-ms/30     # Executes everything in that directory 30 times a minute
#   /etc/cron-ms/600    # Executes everything in that directory 10 times a second
#   /etc/cron-ms/2400   # Executes everything in that directory 40 times a second

basedir=/etc/cron-ms

case "$1" in

   start|restart|reload)
   $0 stop
   mkdir -p /var/run/cron-ms
   for dir in $basedir/* ; do
      $0 ${dir##*/} &
   done
   exit
   ;;

   stop)
   rm -Rf /var/run/cron-ms
   exit
   ;;

esac

# Loops per minute is passed on the command line

loops=$1
interval=$((60000000/$loops))

# Just a heartbeat signal that can be used with monit to verify it's alive

touch /var/run/cron-ms

# After a restart the PIDs will be different allowing old processes to terminate

touch /var/run/cron-ms/$$

# Sleeps until a specific part of a minute with microsecond resolution. 60000000 is full minute

usleep $(( $interval - 10#$(date +%S%N) / 1000 % $interval ))

# Deleting the PID files exit the program

if [ ! -f /var/run/cron-ms/$$ ]
then
   exit
fi

# Run all the programs in the directory in parallel

for program in $basedir/$loops/* ; do
   if [ -x $program ] 
   then
      $program &> /dev/null &
   fi
done

exec $0 $loops

Kind of amazing that you can do all this in less than 50 lines of code.

Monit Script to make sure it keeps running

check directory cron-ms path /var/run/cron-ms
if timestamp > 1 minute then start

start program = "/etc/init.d/cron-ms start"

Companion Program with 1 minute resolution

This is a companion program to run a program every X minutes. you can of course do this in crontab but this makes it easier under some circumstances. This program allows you to:

  • Set the timing in number of minutes just be the directory name and put as many programs in that directory as you want to start.
  • The number of minutes does not need to divide equally into 60.
  • The number of minutes isn't limited to 60. You can run a program every 61 minutes or every 923 minutes if you want.

Both of these programs can be started at the same time from a single crontab entry. (see below) One is for minutes and up. The other is for seconds and down. Between these two you have a very powerful time based execution extension to compliment what cron does.

#! /bin/sh

# Minute Cron
# Usage: cron-min start
# Copyright 2014 by Marc Perkel
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron"
# Free to use with attribution

# Run this script under Cron once a minute

basedir=/etc/cron-min

if [ $# -gt 0 ]
then
   echo
   echo "cron-min by Marc Perkel"
   echo
   echo "This program is used to run all programs in a directory in parallel every X minutes."
   echo
   echo "Usage: cron-min"
   echo
   echo "The scheduling is done by creating directories with the number of minutes as part of the"
   echo "directory name. The minutes do not have to evenly divide into 60 or be less than 60."
   echo
   echo "Examples:"
   echo "  /etc/cron-min/1      # Executes everything in that directory every 1  minute"
   echo "  /etc/cron-min/5      # Executes everything in that directory every 5  minutes"
   echo "  /etc/cron-min/13     # Executes everything in that directory every 13 minutes"
   echo "  /etc/cron-min/75     # Executes everything in that directory every 75 minutes"
   echo
   exit
fi

for dir in $basedir/* ; do
   minutes=${dir##*/}
   if [ $(( ($(date +%s) / 60) % $minutes )) -eq 0 ]
   then
      for program in $basedir/$minutes/* ; do
         if [ -x $program ]
         then
            $program &> /dev/null &
         fi
      done
   fi
done

Launching Both Programs with Cron

To launch both of the above programs from cron every minute edit your /etc/crontab file and add:

* * * * * root /usr/local/sbin/cron-min ; /usr/local/sbin/cron-ms start
Personal tools