Solved illegal variable error when assigning output of date utility to variable

In crontab I have a variable assignment similar to the followinf:
Code:
NOW = $(date -j "+%m-%d-%Y" )
Illegal variable name.

I usually work in bash so sh eccentricities are not well known to me. I have looked at the man pages for sh and tcsh to check the correct syntax but nothing I try appears to work. What is the correct syntax?

Similarly, what is the correct method to interpolate the output from the date utility into an echo string expression inside cron?
 
Last edited:
Then run an instance of sh (or bash, are you sure which one you are using?) by typing sh, then run that assignment there. With the spaces it will give you 'sh: NOW: not found'. Without the spaces the assignment will work.
Leave sh with 'exit' or by pressing Ctrl-d.
 
[...] I usually work in bash so sh eccentricities are not well known to me. I have looked at the man pages for sh and tcsh to check the correct syntax but nothing I try appears to work. What is the correct syntax?

Similarly, what is the correct method to interpolate the output from the date utility into an echo string expression inside cron?
I've found Sh - the POSIX Shell very helpful in developing and debugging sh(1) scripts (POSIX conformant). At Command Substitution you'll also find the appropriate construction for adapting the date:
echo "next year is $(expr $(date +%Y) + 1)"

When using sh(1) and cron(8) & crontab(1), add the appropriate SHELL and PATH entries in crontab(5); see 13.3.1. Creating a User Crontab
___
P.S. for shell scripting: don't look at or use (t)csh
 
Apart from spaces and the shell, there may be one more thing: The plus-sign in that date command, is it interpreted as a command terminator?
 
Cron states that its shell is /bin/sh. When I enter /bin/sh from the command line and view the SHELL variable I see /bin/csh.

Code:
root@vhost01:~ # echo $SHELL
/bin/csh
root@vhost01:~ # /bin/sh
[root@vhost01 root$(__git_ps1 " (%s)")]# echo $SHELL
/bin/csh

When I look at the actual files I see this:
Code:
ls -l /bin/*sh
lrwxr-xr-x  1 root  wheel      19 Dec  7  2021 /bin/bash -> /usr/local/bin/bash
-r-xr-xr-x  2 root  wheel  424304 Dec 24  2021 /bin/csh
-r-xr-xr-x  1 root  wheel  163920 Dec 24  2021 /bin/sh
-r-xr-xr-x  2 root  wheel  424304 Dec 24  2021 /bin/tcsh

Now, I can see that csh and t csh are likely the same. However, /bin/sh most certainly is not /bin/csh. So what is going on?
 
Cron states that its shell is /bin/sh. When I enter /bin/sh from the command line and view the SHELL variable I see /bin/csh.
Code:
root@vhost01:~ # echo $SHELL
/bin/csh
[...] So what is going on?
echo $SHELL is not a reliable method of determining the actual shell you're in* (sh(1) not being your login shell).

For an accurate report on the shell you're in, use ps(1) or procstat(1):
Code:
$ procstat binary $$
  PID COMM		     OSREL PATH
 3660 sh		   1204000 /bin/sh
$ ps -p $$
 PID TT STAT    TIME COMMAND
3660 v3 S	 0:00.11 sh
___
* At login(1):
Rich (BB code):
DESCRIPTION
[...]
     The login utility enters information into the environment (see
     environ(7)) specifying the	user's home directory (HOME), command inter-
     preter (SHELL), search path (PATH), terminal type (TERM) and user name
     (both LOGNAME and USER).
environ(7):
Rich (BB code):
ENVIRONMENT
[...]
     SHELL	      The full pathname	of the user's login shell.
 
Cron states that its shell is /bin/sh. When I enter /bin/sh from the command line and view the SHELL variable I see /bin/csh.

Code:
root@vhost01:~ # echo $SHELL
/bin/csh
root@vhost01:~ # /bin/sh
[root@vhost01 root$(__git_ps1 " (%s)")]# echo $SHELL
/bin/csh

When I look at the actual files I see this:
Code:
ls -l /bin/*sh
lrwxr-xr-x  1 root  wheel      19 Dec  7  2021 /bin/bash -> /usr/local/bin/bash
-r-xr-xr-x  2 root  wheel  424304 Dec 24  2021 /bin/csh
-r-xr-xr-x  1 root  wheel  163920 Dec 24  2021 /bin/sh
-r-xr-xr-x  2 root  wheel  424304 Dec 24  2021 /bin/tcsh

Now, I can see that csh and t csh are likely the same. However, /bin/sh most certainly is not /bin/csh. So what is going on?

FreeBSD's /bin/sh does not set $SHELL, so you still have what you had before you invoked sh.
 
Apart from spaces and the shell, there may be one more thing: The plus-sign in that date command, is it interpreted as a command terminator?
Why would it be interpreted as a command terminator?
echo "next year is $(expr $(date +%Y) + 1)" executes as intended.
 
Why would it be interpreted as a command terminator?
If you put it in the 6th column of your crontab, it will be treated as a command. I remember I had problems with it using a 'find ...' there once.

I gave it a try. Started sh in a terminal and ran NOW=$(date -j "+%m-%d-%Y") && echo $NOW. That showed me the date as expected. Then put the same thing in column 6 of my crontab, which is run by sh too.
That gave me an e-mail to root, indeed interpretation stopped after the plus sign, leading to an unterminated string and thus an error.
 
[...] I gave it a try. Started sh in a terminal and ran NOW=$(date -j "+%m-%d-%Y") && echo $NOW. That showed me the date as expected. Then put the same thing in column 6 of my crontab, which is run by sh too.
That gave me an e-mail to root, indeed interpretation stopped after the plus sign, leading to an unterminated string and thus an error.
The problem can be circumvented by using the expression in a sh-script and calling that in crontab. However, the culprit in the command field of crontab is not the "+" sign but the "%" sign directly following; crontab(5):
Code:
DESCRIPTION
[...]
     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.
Also, it turns out that FreeBSD's date(1) has facilities built in to manipulate the date-time fields. For example,
echo $(date -v +1y -j "+\%m-\%d-\%Y") works as a command in crontab.
 
Back
Top