Obligatory
XKCD… (Though I’m not sure Randall has a
completely accurate understanding of the MAILTO variable which
according to my reading of man cron
is for addresses and not mail
box directories. I could be the wrong one, but no thanks to the man
page. This might be a difference of old school Vixie cron and newer
cronie. See below.)
Vixie vs. Cronie
In the ancient times, a clever guy named Paul Vixie created cron and
it was called cron. And that was fine. But then a lot happened and
Paul had better things to do with his time (apparently) than mess
about with cron. So some different people reimplemented it. Tons of
them really, but the one that seems to be emerging as the best one to
use for practical purpose is
Cronie. Switching to this seems
to cure the Gentoo braindead problem of new vixie-cron crontab edits
not taking effect without a complete process restart. I think I’m one
of the last people to actually use ancient sys-process/vixie-cron
because I have been using it since ancient times and I didn’t know
that it had been cast into the obscurity void.
Basic Usage
Cron uses a "crontab" which is a list of rules for what should happen
when. To simply see what is in your crontab in a read-only
non-destructive way use the crontab
command with -l
for list.
crontab -l
To edit these rules use this command which will properly lock the file and invoke your editor.
crontab -e
If the wrong editor opens the crontab you can fix that with something like this.
sudo apt-get install vim
sudo apt-get purge nano
echo 'export EDITOR=/usr/bin/vim' >> .bashrc
sudo update-alternatives --config editor
Here is a prototypical crontab.
MAILTO=xed@example.xed.ch
SHELL=/bin/bash
# Here is a sample cron tab that explains what goes where.
# Basically, don't put a * in the first two fields unless you
# want a LOT of action.
#
# minute
# | hour(0-23)
# | | day of month(1-31)
# | | | month of year(1-12 or jan, Feb, mAR, etc)
# | | | | day of week(0-6 (0=Sun), or mon, tUE, Wed, etc.)
# | | | | | COMMANDS
# 0 2 * * 0,4 /sbin/something "Runs Sunday and Thursday at 2am"
# */2 means activate when TIME_UNIT MOD 2 == 0
# Normal style of entries.
30 * * * * /home/xed/somegood_hourly_script >/dev/null 2>&1
55 8 * * * /home/xed/somegood_daily_script
# Anniversary reminder example.
0 0 15 4 * echo "File your taxes yet?"
# Example alarm. Play a noise on weekdays at 1430 and 1442.
30,42 14 * * 1,2,4,5 /usr/bin/play -q /home/xed/collection/sounds/cattle.wav
# Check if drive is full. If not, ignore. If it is, send email. At 03h22 Sundays.
22 3 * * 0 df | grep "100. /"
Difficult Things To Specifiy
Every Fortnight
First you can test to make sure your system can use this technique.
* * * * * expr `date +\%M` \% 2 >>/dev/null || date >> ~/testdir/2weekcronttest
This produces something like:
Tue Sep 25 12:40:01 PDT 2012
Tue Sep 25 12:42:01 PDT 2012
Tue Sep 25 12:44:01 PDT 2012
Tue Sep 25 12:46:01 PDT 2012
If you want odd numbered minutes or weeks or whatever, use something like this:
* * * * * expr \( `date +\%M` + 1 \) \% 2 >>/dev/null || date >> ~/testdir/2weekcronttest
This isn’t too exciting since you can get every other minute by doing
a */2
in the minute field. But it quickly proves the idea which will
also work on weeks where the normal syntax breaks down.
If the test works out, then you can see that replacing the %M
with
%W
will give you a cron job that runs on every even (or odd) week of
the year. If the test doesn’t work, see the section on percents below.
Here’s a cron rule that runs biweekly (fortnightly):
0 11 * * thu expr `date +\%W` \% 2 >>/dev/null || /usr/local/bin/indexthedb
Mailing
First note the "MAILTO=" line which will take all standard output of the commands run by cron and send them to that specified email address.
Mail is generally a separate problem from cron and to make sure automatic notifications work, make sure that manual mail sending is good to go.
cal 2000 | mail -a "From: raven back-upper <logging@xed.com" \
-s "subject goes here" logging@xed.com
Make sure you have mailx
and ssmtp
installed (Gentoo anyway) and
look at /etc/ssmtp/ssmtp.conf
.
If this works as planned then you can specify some mailing jobs in cron. That would look something like:
0 0 * * 0 echo "Weekly Backup Reminder" | /usr/bin/mail \
-a "From: $(hostname) <logging@xed.ch>" \
-s "Cron testing from sad" logging@xed.ch
You can try \
but I just put them here for illustration. Normally
I’d just have all this on one line to be safe.
Caveats
Percent
In crontabs, "%" delimits the command’s standard input (the first percent) or signifies a new line within that input. The only use I can imagine for this is mailing things.
55 * * * * mail -a "From: Crontest <crontest@xed.ch>" \
-s "A Test Of Cron" \
xed@blackswan%This is a test.%This should be line 2 of the message.
This is helpful when you want cron to just send you reminder notes. I find, however, that pipes work just fine making this percent functionality more of a nuisance than anything.
It is theoretically possible to escape this behavior with a backslash
like \%
but I’ve had trouble getting that to work sometimes.
Another way to get a real "%" without including it on the command line
is to use $'\x25'
which is a bit complex but mostly works without
messing up other things. This is a Bash substitution and it’s
important to note that the vixie-cron daemon sets the SHELL
value to
/bin/sh
by default. But you can add a line with SHELL=/bin/bash
so
that this kind of fancier substitution does work. Of course this may
mess up other things.
Here’s a diagnostic sequence designed to regularly capture working conditions every 15 minutes in order to troubleshoot random failures. (Heat related? Memory? What kind of jobs were being run?)
2,17,32,47 * * * * SL=/local/xed/sensorlog ;\
date '+========== \%Y\%m\%d-\%H\%M' >>$SL;\
sensors >>$SL ; freeh -h >>$SL ;\
top -bn1 | head -n20 >>$SL
I conclusively had this work in cronie
on CentOS 7.
Definitely test your entry before relying on it if it includes "%".
Gentoo
For some reason, changes made on some Gentoo systems with crontab -e
are not
taking effect. The vixie-cron daemon must be restarted:
$ sudo /etc/init.d/vixie-cron restart
I don’t know why that is but it’s wise to check to make sure that cron does what you think it’s supposed to be doing.
See my aforementioned remarks about Cronie as perhaps a better choice.
at
at
is the lesser known little brother of cron
. The at
command is
similar to cron
in that it schedules jobs to be run at a later time,
but at
specifies a single fixed future point in time for the job to
run as opposed to periodically.
at
…
-
…has a daemon process (
atd
) similar tocrond
to manage jobs. -
…is for jobs set to run at specific times, not periodically (like
cron
). -
…can also schedule jobs for when the cpu is unloaded.
-
…can email you when the job is complete.
-
…preserves environment it was run from (cron does not).
at Examples
Here are some simple examples. This is a very normal kind or thing:
echo '/home/xed/mknewyearbackups.sh 2014' | at midnight January 1 2014
I’m actually not sure if midnight
is after the day specified or
before. Need to check that.
Here is a good way to get rid of temp files:
$ echo "rm /tmp/mytempfile" | at now + 10 minutes
at Management
-
batch
is an alias ofat
which runs jobs when the CPU load is low. -
atq
lists pendingat
jobs . -
atrm
removes pendingat
jobs . -
See
man at
for all the details. -
Also this web page is useful (it can be hard to search for good info on
at
).
at
can use /etc/at.allow
and /etc/at.deny
. It may be smart to
make these as symlinks to /etc/cron.allow
and /etc/cron.deny
if
they exist.