This question already has an answer here:
Closed last year.
I have a crontab
that looks like
0 0 * * * pg_dump DB_NAME > /path/to/dumps/`date +%Y%m%d`.dmp
which works fine when I run it manually, but not when cron
runs it. After digging through the logs, I see
Dec 12 00:00:01 localhost crond[17638]: (postgres) CMD (pg_dump DB_NAME > /path/to/dumps/`date +)
It looks like a problem with percent signs, but the man
page doesn't even contain the percent character at all, so I thought they were alright.
You have to escape percent signs with a backslash:
0 0 * * * pg_dump DB_NAME > /path/to/dumps/`date +\%Y\%m\%d`.dmp
From man 5 crontab
:
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 "\".
There's another characteristic problem that can affect programs run by cron
as compared with the command line (other than the interpretation of '%
' signs described by Robert Gamble).
That difference is in the environment. If the program run relies on special environment variables, then it will work when you run it from the command line, with the environment you normally use, and it will likely work if you run it with at
because that captures the environment when you create the job. But cron
does no special environment setting.
I habitually, therefore, configure cron
to run scripts by absolute pathname, and that script does the environment setting that I need (adds my $HOME/bin
directory to PATH, for example). I even have a standardized infrastructure for this - a shell script that sets the environment and runs other programs.
# @(#)$Id: crontab,v 4.2 2007/09/17 02:41:00 jleffler Exp $
# Crontab file for Home Directory for Jonathan Leffler (JL)
#-----------------------------------------------------------------------------
#Min Hour Day Month Weekday Command
#-----------------------------------------------------------------------------
0 * * * * /usr/bin/ksh /work1/jleffler/bin/Cron/hourly
1 1 * * * /usr/bin/ksh /work1/jleffler/bin/Cron/daily
23 1 * * 1-5 /usr/bin/ksh /work1/jleffler/bin/Cron/weekday
2 3 * * 0 /usr/bin/ksh /work1/jleffler/bin/Cron/weekly
21 3 1 * * /usr/bin/ksh /work1/jleffler/bin/Cron/monthly
The script in /work1/jleffler/bin/Cron
sets the environment and then runs the script of the same name in /work1/jleffler/bin
to do the real work. The names in the Cron
sub-directory are actually all links to the same script.