1

I want to run a cronjob daily at a specific time range but only once in that period. How is that possible?

I see a possibility in anacrhon but don't know how to set up such scenario.

LeMike
  • 275
  • Why do you need a range? You can specify a specific time within that range like 4:30. – Dan Aug 19 '13 at 17:28
  • Because I don't want backups done while I work and can't ensure that the PC is turn on at a particular time. – LeMike Aug 19 '13 at 17:58

3 Answers3

2

You can place you cronjob in /etc/cron.daily/ and it will automatically run in that timeframe.


Edit:

Sorry, I was referencing an old Debian installation where anacron wasn't installed by default. In that case /etc/cron.daily/ was executed by /etc/crontab on 6:25. But newer Debian installations (and so does Ubuntu) install anacron by default and so /etc/cron.daily/ will be executed by /etc/anacrontab five minutes after anacron was started or every new day.


To achieve your schedule (from the comments) you can set up a cronjob that will e.g. every 10 min between 3-6 start either anacron that will take care that the backup job only run once or you can write a custom controll script.

1. Alternative: anacron

mkdir ~/.local/share/anacron_spool
echo "1 0 backup.daily /path/to/backup.sh" > ~/.config/anacrontab
(crontab -l; echo "*/10 3-6 * * * /usr/sbin/anacron -s -t $HOME/.config/anacrontab -S $HOME/.local/share/anacron_spool") | crontab -

This will make anacron to serialize (-s) run all jobs defined in ~/.config/anacrontab. Because by default only root has write permission to write to /var/spool/anacron/ where the timestamps are stored we use a custom spool-dir (-S). If all jobs are done for today anacron will exit.

2. Alternative: custom controll script

Open an editor (e.g. sudo nano /usr/local/bin/run_once_a_day.sh) and paste this:

#!/bin/bash
SPOOL="$HOME/.local/share/run_once_spool/"
if [ $# != 2 ]; then
    echo "Usage: $(basename $0) <job-identifier> <command>"
    exit 1
fi

if [ ! -d $SPOOL ]; then mkdir $SPOOL fi

if [ -e ${SPOOL}${1} ]; then last_run=$(cat ${SPOOL}${1}) else last_run=0 fi

today=$(date +%Y%m%d) if [ $last_run != $today ]; then $2 echo $today > ${SPOOL}${1} fi

Press CTRL+O to save and CTRL+X to exit. Make it executeable and add a cronjob that will start it periodicaly with:

sudo chmod 755 !$
(crontab -l; echo "*/10 3-6 * * * /usr/local/bin/run_once_a_day.sh backup.daily /path/to/backup.sh") | crontab -
Germar
  • 6,377
  • 2
  • 26
  • 39
  • Please add information where to set-up the timeframe. Just placing the file there won't do I guess. ;) – LeMike Aug 19 '13 at 17:57
0

A cron job will run every time only once on a given schedule/time. So, if you set a cron job at which time do you wish between 3 and 6, this will run only once at a specified time. Only once, and never more than once!

See more explanations and some examples at: http://en.wikipedia.org/wiki/Cron

Radu Rădeanu
  • 169,590
0

I think the simplest work-around is to have a wrapper script being called every N minutes during the interval, but it starts by checking for the existence of a "locker" file it creates upon execution.

#!/bin/bash
[[ -f /dev/shm/cron-once-script-lock ]] && exit 0
touch /dev/shm/cron-once-script-lock

actualcronjob.sh # or whatever non-script command it may be

# end of wrapper script

And the cron line would be like:

*/10 3-6 * * * /wherever/the/script/is/wrapper-script.sh

Or perhaps

*/10 3-6 * * * bash /wherever/the/script/is/wrapper-script.sh

The only caveat is that cron runs under a restricted "environment" and you may need to export environment variables and this sort of stuff, but that's another subject altogether.