Cron files copied directly into /var/spool/cron/crontabs do not execute

Copying a crontab file directly into /var/spool/cron/crontabs/<username> does not schedule the job for execution.

crontab -l shows the file contents, so cron is at least somewhat aware of it. But it never gets executed.

If I edit with crontab -e and make a meaningless change, then cron somehow gets notified and all is well.

Is there a programmatic way to achieve the same effect?

Referring to this question, I have tried these commands with no luck:

sudo service cron reload
sudo service cron restart
sudo /etc/init.d/cron force-reload

P.S. Yes, I know copying crontabs directly into /var/spool is not the usual way to do things. This is part of a larger task of setting up new cookie-cutter aws ec2 ubuntu instances via docker, and I want them to come "pre-loaded" with specific crontabs.


From your comment:

The file was owner root and group root, and I changed it to group crontab to match the other files in that directory. But that had no effect.

In /var/spool/cron/crontabs/ the crontab for the user ratbert should be named ratbert and be owned by ratbert. Maybe you did not change the owner; or permissions; or…

I tested in Kubuntu 21.10 and it seems the factors are at least:

  • name (should be the username)
  • owning user (should be the username)
  • owning group (should be crontab)
  • permissions (should be 600; I haven't checked all possibilities but certainly some more restrictive and some less restrictive permissions are wrong)
  • mtime(?)

If cron loads a file with the right ownership and permissions, it will use it. If the file gets modified, it will be reloaded. You can break some things (e.g. change the owning group) and cron will keep using the version it has already loaded until you modify the file or otherwise cause cron to try to load anew (e.g. by restarting it). On the other hand if cron tries to load a file with some wrong settings then it will stop using the old version, won't use the new one, won't try to reload it even after you fix the settings. I think it will try to reload after you modify the file.

Therefore restarting cron after you manually set all the things up is a good idea. This way it will notice the file in its target state.

Still the things must be set up right. I strongly suspect you created a file with wrong ownership and/or permissions. I notice crontab -l is not picky and can print a file that wouldn't work. crontab -e saves changes and fixes things. This is why crontab -l did not fail and crontab -e did help you. If you compare ls -l /var/spool/cron/crontabs/ratbert from before and after crontab -e that fixes things then probably you will find out what was the cuplrit in your particular case.

I think we can set the things up manually and cron will work, if only we set all the things right. But doing this manually may not be a good idea in the first place. Yes, if you are going to prepare a filesystem (disk image) for another machine then you may want to do this. The other machine will start its cron later and if you set up everything right then it should work.

Normally, when working in the target OS, do not use cp, chown or chmod for this. Use the crontab [ -u user ] file syntax. See man 1 crontab:

crontab [ -u user ] file
crontab [ -u user ] [ -i ] { -e | -l | -r }

[…]

The first form of this command is used to install a new crontab from some named file or standard input if the pseudo-filename - is given.

The POSIX specification does not mention -u, the option is not portable; still the crontab file form is portable and this is the Right Way to install a file as a crontab entry. In Ubuntu you can use -u. An example command is:

crontab -u ratbert /path/to/predefined/file

The tool will set up everything for you and you won't even need to restart cron.