15

I have the following cron jobs defined.

55  8   *   *   3   /usr/bin/php /home/mark/dev/processes/customClient/events.php > /home/mark/dev/processes/customClient/events-`date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`.csv
0   9   *   *   3   /usr/bin/echo 'The csv for last week, trying my hand at automatiging this' | /usr/bin/mutt <emailaddress> -s 'Events from `date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`' -a '/home/mark/dev/processes/customClient/events-`date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`.csv'

It seems to work properly if I run it the above command directly from the command line. But when I checked the running of the script this morning I got an e-mail stating (I'm paraphrasing because I accidentally deleted them) that the back ticks weren't closed properly.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Mark D
  • 1,175
  • FYI I just retested the cron jobs and got the following errors.

    /bin/sh: 1: Syntax error: EOF in backquote substitution

    For the first cron job.

    /bin/sh: 1: Syntax error: Unterminated quoted string

    For the second cron job.

    – Mark D Sep 12 '12 at 15:50
  • 2
    Backticks are deprecated for this very reason; changing to $(...) will help you deal with the quoting issues... – jasonwryan Sep 12 '12 at 19:12
  • 2
    You definitely want to check a question of mine. It has an answer by Stephane Chazelas that explains how you can create an interactive shell that is identical to the environment your cron job will see. If you walk through his little procedure, you get a prompt and you can test your cronjob step by step and see where it fails. unix.stackexchange.com/a/56503/16841 Sure it isn't a 100% match for your question, but it can help you troubleshoot crontab issues. – jippie Nov 23 '12 at 22:59

3 Answers3

36

There are three common causes for cron job commands to behave differently compared to commands typed directly into an interactive shell, in rough order of commonness:

  • Cron provides a limited environment, e.g., a minimal $PATH, and other expected variables missing.
  • Cron invokes /bin/sh by default, whereas you may be using some other shell interactively.
  • Cron treats the % character specially (it is turned into a newline in the command).
  • Cron doesn't provide a terminal or graphical environment.

You must precede all % characters with a \ in a crontab file, which tells cron to just put a percent in the command. Remember that when you use the date command in a cron job.

55  8   *   *   3   /usr/bin/php /home/mark/dev/processes/customClient/events.php > "/home/mark/dev/processes/customClient/events-$(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d).csv"
0   9   *   *   3   /usr/bin/echo 'The csv for last week, trying my hand at automatiging this' | /usr/bin/mutt <emailaddress> -s "Events from $(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d)" -a "/home/mark/dev/processes/customClient/events-$(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d).csv"

I also fixed some quoting problems:

  • This wasn't causing you problems other than with legibility, but you shouldn't use backticks for command substitution. Use $(…) instead: its parsing rules are simpler.
  • Always use double quotes around variable and command substitutions: "$somevariable", "$(somecommand)". Here the lack of quotes was harmless because the date command never returned any special character for the formats you used, but you have to carefully remember which characters are special and check this every time you leave a substitution unquoted. Keep it simple, always use double quotes unless you want field splitting and filename generation to happen on the result.
  • You had some single quotes preventing expansion around some command substitutions. Use double quotes instead.
16

I strongly recommend putting any non-trivial cron jobs into their own shell script file, for many reasons:

  • Easier to debug: you can just run the script instead of copy pasting a long line, and with the right shebang line, it behaves much more predictably than if you had the same commands directly in the crontab
  • Easier to read: no need to make it a 200+ character one-liner, you can format it nicely so it's easy to read and understand for everyone
  • Add the script to version control
janos
  • 11,341
0

You seem to have nested ' in the mutt command:

'Events from date +%Y-%m-%d --date='last Wednesday'-date +%Y-%m-%d'

Try using " instead of the inner ' so that the statement reads

'Events from date +%Y-%m-%d --date="last Wednesday"-date +%Y-%m-%d'

daisy
  • 54,555
  • I'm not sure that's what the problem is. But after giving it a shot in both cron jobs the execute without any success. – Mark D Sep 12 '12 at 15:50