Shell – Best way to ensure that a script is run once a period

cronscriptingshell-script

I need a certain script to run once a month (others viewing this question may need it to be run once a day/week/year/5-day, etc).

I know I can use cron to do so with:

0 0 1 * * ./script.sh

But what if the machine happens to be offline during that interval (power out on the 1st of a particular month as an example).

Is there an elegant solution to this? Or Would I have to include a sub-routine in that script to set an I've-run-this-month-already value, and then another script run every day of the month (or on boot) to check that value?

Update:

I need my script to run once per month at the very beginning of the month. While writing a script to accomplish a number of things, I created the below piece of code. I'm only putting it here in case someone finds it useful after finding this question.

# CHECK FOR THE OLD_MONTH FILE
if [ ! -e /usr/local/bin/system/old_month ]; then
        # CREATE IT IF IT DOESN'T EXIST WITH THIS MONTHS DATE
        echo `date` | awk '{print $2,$6}' > /usr/local/bin/system/old_month
fi

# CREATE A NEW FILE EVERY TIME THIS SCRIPT IS RUN WITH THIS MONTHS DATE
echo `date` | awk '{print $2,$6}' > /usr/local/bin/system/this_month

# CHECK IF OLD_MONTH AND THIS_MONTH ARE NOT THE SAME
if ! cmp /usr/local/bin/system/this_month /usr/local/bin/system/old_month > /dev/null 2>&1 ;
then
        # RUN YOUR RELEVANT CODE HERE #
        echo `date` | awk '{print $2,$6}' > /usr/local/bin/system/old_month     # UPDATE THE VALUE IN OLD_MONTH SO THAT THEY WILL MATCH NEXT TIME
fi

Best Answer

You can use Anacron for this, it is designed to run jobs at certain intervals without assuming that the system is on continuously. If a job is supposed to be run every month, Anacron will check whether it has run in the previous month, and run it if it hasn't (and remember that it doesn't need to run it again for another month).

In Debian derivatives, Anacron works nicely with Cron to take care of /etc/cron.{daily,weekly,monthly} appropriately (so you simply define your monthly task as a monthly job in /etc/cron.monthly, and it will be run appropriately).

On other systems, you would define your monthly task in /etc/anacrontab.

Related Question