How do you set a DATE variable to use in a log for crontab output?

39,015

Solution 1

Cron is not a shell - it does not parse commands in the same way that a shell does. As such, your variable is assigned as if it was static text.

There are three solutions I know of to this problem:

Option 1: Use a shell script to generate your command, include whatever variables and logic you want - and call that shell script from cron.

* * * * * /path/to/myscript.sh

Where myscript.sh:

DATEVAR=`date +20\%y\%m\%d_\%H\%M\%S`
echo $DATEVAR >> /tmp/crontab.log

Option 2: Include the date command directly in your command, and, since the entire command is passed to the shell, the date will be processed and replaced with an actual date.

* * * * * /bin/echo `date +20\%y\%m\%d_\%H\%M\%S` >> /tmp/crontab.log

Option 3: Set the string variable in cron, and pass that to your command to be processed (note - the percent signs do not need to be escaped, and the variable itself is wrapped in $() to execute it in a separate shell - backticks should work the same):

DATEVAR=date +20%y%m%d_%H%M%S
* * * * * /bin/echo $($DATEVAR) >> /tmp/crontab.log

(In all the cases above, you can, of course, use a variable for the log path, instead of 'hard coding' it.)

Solution 2

The "problem" is that cron uses the percent sign as a special character. You have to quote it so it is ignored by cron, but not by the shell. Like most of the folks who I saw that spent hours upon hours tinkering around with when and how and where to quote what, I went through that hack-and-slash as well.

Here's the solution I found that has worked on all flavors of *nix:

# Define the percent sign in a variable.
P=%
#
# Now use it in a $() subshell. Don't get freaked about the double quotes
# inside the $(), they are processed by the subshell.
57 2 * * * root /bin/echo "[CRON] at $(date "+${P}d-${P}b${P}Y")" 1>>/tmp/crontab.log 2>&1

As the old saying in the world of Perl: there is always more than one way to do it. I am not saying this is the only way or the best way -- what I am saying is that this works for crontab entries running on CentOS, Debian, Ubuntu, Mac, and AIX, so this is what am sticking with.

Share:
39,015

Related videos on Youtube

qodeninja
Author by

qodeninja

I write qode mostly for myself... out of curiosity for solving problems, understanding how things work or making (sometimes unnecessarily) complex systems to only simplify them later (once I discover alternative strategies). For whatever reason, I like torturing myself with Regular Expressions, SED, Bash and JavaScript (Node), but have found a growing (painful) love with Python. Having said that, I enjoy scripting languages a lot more than compiled languages, and I've coded in almost all of the major modern ones except Ruby. I'm a secret Turing Machine/Computer Grammars/Regular Expressions nerd, and have written my own mini compilers and toy languages. I'm constantly writing command dispatchers that I later write scripting languages for; it's an addiction. There's plenty room for me to grow and learn still; and I appreciate the wisdom of grey beards and lady wizards even if I don't always follow their sage advice. FOSS is hella cool; cool projects are cool. Find me online if you have ideas. I'm a really bad programmer but I'll write a line or two for the betterization of the peoples. Edit: I recently discoved that VI is really just SED with wings. Still not using VI. Nano or bust.

Updated on September 18, 2022

Comments

  • qodeninja
    qodeninja almost 2 years

    I was playing aroudn with some variations of date like

    DATE = $(date)
    

    but that didnt work either

    crontab -e

    CRONLOG=/tmp/log/crontab.log
    DATEVAR=`date +20\%y\%m\%d_\%H\%M\%S`
    * * * * * echo $DATEVAR >> /tmp/log/crontab.log
    */2 * * * * echo "$DATEVAR hello" >> ${CRONLOG}
    */1 * * * * echo 'every minute' >> ${CRONLOG}
    

    this just outputs the text as is...

    I want to create a log entry in crontab.log with a timestamp on each update

    How can I do this on CentOS 6?

    UPDATE

    DATEVAR=date +20%y%m%d_%H%M%S
    */1 * * * * /bin/echo [CRON] $($(DATEVAR)) >> /tmp/log/crontab.log
    

    rendered only [CRON] and NOTHING when I tried it =/

  • qodeninja
    qodeninja over 12 years
    thanks for the great feedback +1, i tried to add it to the crontab but doing that didnt work =/ it never renders DATEVAR
  • cyberx86
    cyberx86 over 12 years
    I just did this on a RHEL/CentOS6 compatible system and it gave the expected result (i.e. added a new line to the file with the date). Which option (of the 3 above) did you try, and what was the result - be specific - and was there an error in /var/log/cron? (if you use the script option, a) don't forget to chmod +x and b) try it on its own first (i.e. not through cron))
  • qodeninja
    qodeninja over 12 years
    option 3 =], I had tried to do that before but it didnt render. But now im noticing you did something a lil dif. why did you double up the $($(DATE))? see my update above
  • cyberx86
    cyberx86 over 12 years
    You have a typo in the update you added - it is $($DATEVAR) not $($(DATEVAR)). Think of it this way - $() - that is, the outer bracket - launches a new shell to process whatever is in the brackets. In this case, the variable $DATEVAR is set to a string and is passed to the shell. $(DATEVAR) is nothing - because DATEVAR is nothing (i.e. is it missing a $ to identify it as a variable). You could also use backticks around $DATEVAR to get the same result
  • qodeninja
    qodeninja over 12 years
    fair enough. updated it. lets try this bad boy! -- Hazaaah! it worked lol