When your computer is shut down (or the cron daemon is otherwise not running), cron jobs will not be started.
If you have jobs that you would like to run after the fact during those times when the computer is shut down, use anacron. Installed by default, see "man anacron", "man anacrontab", or the file /etc/anacrontab for more info.
Ubuntu uses anacron by default for crontab entries in:
/etc/cron.daily
/etc/cron.weekly
/etc/cron.monthly
leaving the remaining crontabs to be handled by the main cron daemon, specifically:
/etc/crontab
/etc/cron.d
/var/spool/cron
NOTES
Anacron itself does not run as a daemon, but relies on system startup scripts and cron itself to run.
On the Ubuntu 8.04 box I'm looking at, /etc/init.d/anacron is run at boot, and again by cron each morning at 07:30.
The README at /usr/share/doc/anacron/README.gz has a slight bit more info than is contained in the manpages.
EXAMPLES
For simple "daily", "weekly", "monthly" jobs, put a copy of or a symlink to the script in one of the /etc/cron.{daily|weekly|monthly} directories above. Anacron will take care of running it daily/weekly/monthly, and if your computer is off on the day the "weekly" scripts would normally run, it'll run them the next time the computer is on.
As another example, assuming you have a script here: /usr/local/sbin/maint.sh
And you wish to run it every three days, the standard entry in /etc/crontab would look like this:
# m h dom mon dow user command
0 0 */3 * * root /usr/local/sbin/maint.sh
If your computer was not on at 00:00 on the 3rd of the month, the job would not run until the 6th.
To have the job instead run on the 4th when the computer is off and "misses" the run on the 3rd, you'd use this in /etc/anacrontab (don't forget to remove the line from /etc/crontab):
# period delay job-identifier command
3 5 maint-job /usr/local/sbin/maint.sh
The "delay" of "5" above means that anacron will wait for 5 minutes before it runs this job. The idea is to prevent anacron from firing things off immediately at boot time.
Here's what I did, and it seems to work in this situation. At least, it shows me an error, whereas running from the command line as the user doesn't show the error.
Step 1: I put this line temporarily in the user's crontab:
* * * * * /usr/bin/env > /home/username/tmp/cron-env
then took it out once the file was written.
Step 2: Made myself a little run-as-cron bash script containing:
#!/bin/bash
/usr/bin/env -i $(cat /home/username/tmp/cron-env) "$@"
So then, as the user in question, I was able to
run-as-cron /the/problematic/script --with arguments --and parameters
This solution could obviously be expanded to make use of sudo or such for more flexibility.
Hope this helps others.
Best Answer
Because a period of 45 days does not divide nicely into the weeks, months, or years of the Gregorian calendar there is no way to restrict which dates your script runs on and still have it execute on all of the days which you want.
Because of that you will need to have your command run every single day and have the command itself return without doing anything on 44 out of every 45 days.
For example if you want the script to run at 03:17 the command could look like this:
And inside the script you could do this:
The
!= 0
part can use a different number depending on which day you want it to run the first time. And you can choose to put that extra logic in the crontab rather than in the script, though I personally find it more readable to do it in the script.Notice that if your timezone uses DST you may need to tweak the above to avoid the schedule shifting by a day when the clock is adjusted. The exact details depend on which timezone and which time of day you choose to run your script.