A crontab fails to run a task with a date command

19 Views Asked by At

In a project, I am trying to run a command that processes data from the day before (a rather common use case).

I am running it from a Docker container (python:3.11 derived) and therefore a Linux system, but it's unlikely to be related to this specific system.

In order to find the previous date, I use the following command:

date +%F --date="1 day ago"

The +%F (full date) formats the output as YYYY-MM-DD. (the --date option is GNU-specific. On BSD derived systems, including MacOS, the equivalent would be -v1d)

In order to troubleshoot the problem, I prepared a small crontab with the following tasks (in my container, it is to be put at /etc/cron.d/crontab)

* * * * * root echo "Hello World" 1>> /some/path/log/hello_world.log 2>&1
* * * * * root echo Hello `date` 1>> /some/path/log/hello_today.log 2>&1
* * * * * root echo Hello $(date +%F --date="1 day ago") 1>> /some/path/log/hello_yesterday.log 2>&1

Rather oddly, the hello_world.log and hello_today.log work, but the hello_yesterday.log is not created.

At first I was suspecting a problem related with command substitutions, but the second task (hello_today.log) works, and its content is correct. Then, I wondered if it could be the syntax of command substitution (backticks against dollar-parentheses), since the dollar-parentheses syntax was not supported by legacy versions of shells. I verified that both syntaxes work with hello_today.log

What is mind-blowing is that the third task doesn't even create the log file, so no error message stored in this file can help. It's like if the line was skipped entirely.

1

There are 1 best solutions below

1
Corentor On

I eventually found the solution in another Stack Overflow answer

I have still decided to share this question/answer for this specific case, for it could help other people.

The problem had nothing to do with command substitutions in crontab, but simply with the percent sign. It has a special meaning in crontab and must be escaped with a backslash when used by other commands.

In this specific case, the task must be rewritten:

* * * * * root echo Hello $(date +\%F --date="1 day ago") 1>> /some/path/log/hello_yesterday.log 2>&1