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.
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: