By Erik Letson, July 20th, 2020 (blog index)
Recently, I was in the process of implementing an automated system on my server to accomplish some repetitive task. As is usual for jobs like this, I was using cron, as I had done many times before. The script that I was having cron run was a good bit more complicated than most other cron scripts I had run before, but I didn't expect it to be too much trouble, especially coming from cron's end. Boy was I wrong...
The specific ways I got my script working are not really what I wanted to post about here. Rather, in the course of researching my problem, I learned lots of little caveats that have to do with cron in general, and I tought I would compile them here, for my use and others'. If you are having difficulties getting cron to obey you, maybe some of the pointers here can help.
Cron (at least Vixie cron, and POSIX cron in general) expects there to be a newline character at the end of the crontab. This is because the "newline" character represents a terminating line, and if a file does not end in such a character, the line is not really terminated. In the past, most editors understood this and worked with this fact automatically, but many newer text editors do not automatically add a newline character to the final line of a file (though some, notably vi and vim, do). This can lead to issues where a crontab is non-functional without having any obvious syntactical errors anywhere. And what's worse is, cron won't even warn you that you have a mangled crontab! It will simply silently fail. Its best to always end a crontab with an empty line, just in case.
Cron's running environment is going to be *radically* different than the crontab owner's environment. In particular, the PATH variable will likely be significantly more limited in scope, meaning that some commands that might "just work" when you type them into your user's terminal will fail when they are included in cron commands, since they will not be on the path for cron. In my case, sendmail was one such command, but there are many others. Schedule a cron job that will put the output of the env command into a file, then check out this file and compare it to what env outputs for your regular user. There will be significant differences. If you aren't sure whether or not a command will be on cron's PATH, best practice is to refer to it explicitly with an absolute path.
Saving alone inside crontab -e doesn't do anything. A crontab will only be installed (an therefore used) when you EXIT the editor that crontab -e started. So :w in vim isn't helping you out any unless you also :q!
Cron may not automatically use your new crontab without your restarting of the cron daemon first. Do this on systemd with service cron restart, or, on OpenRC systems (such as Gentoo), with rc-config [CRONDAEMON] restart, where $CRONDAEMON is the name of your cron service (I use cronie).
The percent sign ( % ) has a special meaning in crontab syntax, and cannot be used in cron commands without escaping it.