I learned something new—very minor, but still new—about cron jobs this week: if you use a per cent sign in the scheduled command, you need to escape it.
The documentation about cron can be hard to find. man cron
shows “cron (8) - daemon to execute scheduled commands” (the 8
, according to man man
, meaning it’s a system administration command). But if you’re trying to figure out how to schedule a job, you don’t want to know about the daemon that takes care of the work. man crontab
shows “crontab (1) - maintain crontab files for individual users”, which is the command to edit the crontab. The format of the crontab is found with man 5 crontab
(5 meaning it’s to do with “file formats and conventions”), which shows “crontab (5) - tables for driving cron”.
I always forget how to schedule cron jobs beyond minute and hour, so pretty much every time I set up a new one I need to run man 5 crontab
. I must have looked at it hundreds of times, but I never noticed about % until I ran into a problem.
I had something like this set up:
0 5 * * * YYYYMMDD=`date +%Y%m%d`; touch ~/tmp-$YYYYMMDD.txt
That creates a date-stamped file at 5 am every day. It works fine on the command line, but when cronned up I got these errors in email:
/bin/bash: -c: line 0: unexpected EOF while looking for matching ``'
/bin/bash: -c: line 1: syntax error: unexpected end of file
That didn’t make any sense, but this explained it:
The ``sixth’’ field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline or % character, will be executed by /bin/sh or by the shell specified in the SHELL variable of the crontab file. Percent-signs (%) in the command, unless escaped with backslash (\), will be changed into newline characters, and all data after the first % will be sent to the command as standard input. There is no way to split a single command line onto multiple lines, like the shell’s trailing “\”.
This works:
0 5 * * * YYYYMMDD=`date +\%Y\%m\%d`; touch ~/tmp-$YYYYMMDD.txt
I’ve never had occasion to use % to send STDIN to a command, or seen it used, but there must be some reason for it somewhere in Unix history.