# Difference between using crontab and /etc/cron.hourly,daily,weekly

I have a scheduled script that does an hourly svnsync backup of our Subversion repositories. I was running it from an entry in the root crontab without problems, but decided I'd like to run it from /etc/cron.hourly instead for extra visibility (and because one of our engineers accidentally deleted the crontab because he thought "crontab -r" meant "read the crontab ;-))

The svnsync commands in the cron.hourly script all fail with a message saying that the SSL certificate for the SVN repository needs to be accepted (this is the message you get interactively the first time that user accesses the SVN repository, but once the certificate I accepted the message doesn't come up again).

So it seems to me that the script is being executed under a different user environment when run from cron.hourly than when it's run via the root crontab. Can anyone explain the difference ?

UPDATE: I should have mentioned my distro, I'm using anacron on CentOS 5.1.

UPDATE 2: Thanks for the suggestions so far; I think this is turning into more of a Subversion question. I always try to encapsulate my environment into my scripts, but the problem here is that I'm not sure what it is in (or lacking in) the environment that makes SVN ask for the SSL certificate to be accepted when I run my script from cron.hourly. I'm guessing it's something to do with the way that the run-parts script is executed.

• It would be useful to include your distro and cron package of choice. – Dan Carley Jul 9 '09 at 21:53

You want to use the '--config-dir' option to let it know where to find the accepted cert (e.g. ~/.subversion by default).

That said, I'm almost certain you'd be better off calling svnsync from the hooks/post-commit script instead, as suggested elsewhere. Then your mirror is always in sync, rather than in sync with where your master was an hour ago.

On Debian/Ubuntu system cron.daily|weekly|montly are started from the main crontab.

17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )


Also keep in mind that you probably could place a crontab fragment in /etc/cron.d/

As you can see there isn't anything particularly special about this environment. At least on Debian/Ubuntu it all is run as the root account.

When I write cron scripts at the very start of the script I always set my PATH and other environment variables i will be using, so I can be certain that it will work correctly in any environment.

A regular system-wide crontab is a specific user's crontab and it has the username field, as used by /etc/crontab.

Using scripts in /etc/cron.* (hourly, daily, weekly, monthly) is a cleaner and easier way (prevents common syntax errors) of configuring crontab for root user and this is handled by run-parts which run scripts or programs in a directory. All these rules are still defined in system-wide crontab by default (/etc/crontab), so it's the same thing.

When cron jobs are handled by run-parts, are easier to debug, as you can simply test which scripts would be exactly run (without running them yet) by:

sudo run-parts --report --test /etc/cron.daily


My first wild guess would be check your HOME variable.

On my Centos system, man 5 crontab says:

Several environment variables are set up automatically by the cron(8) daemon. SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd line of the crontab’s owner.

So, if you have not specified otherwise, root's crontab would use /root for HOME. But in /etc/crontab (which is where /etc/cron.hourly is run from, via run-parts), HOME is set to / (and SHELL to /bin/bash instead of /bin/sh).

I do not know about svnsync, but subversion does use a ˜/.subversion/ directory, so that could depend on HOME.

On my RHEL 5.1 system, the PATH environment variable is set from /etc/crontab. All that stuff up at the top is stuff that's fed into the environment.

If you restart cron, then the first time it runs(if from /etc/crontab or /var/spool/cron/\$USER) it will make a note of it in /var/log/cron. Otherwise it will just note that cron.hourly ran

My crontab is set to the following:

01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly


What you could do is put something like the following into /etc/cron.hourly:

env > /tmp/cron.env


Then inspect the file when it comes around, and either modify your script(if you can) to set the environment properly, or write a short wrapper script that your crontab will call.

/var/log/messages (or your distro's equivalent) should tell you the specifics of what command was run when and as which user.

Never assume there is anything in the environment. Always code defensivly. You have a whole file to put whatever environment set up stuff you want in there. Use it.

Not much other the portability, the last time I checked (in Debian) it was recommended to put stuff in cron.hourly (and the others) and not directly into crontab if you wanted to create a package with your stuff.