LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Ubuntu (https://www.linuxquestions.org/questions/ubuntu-63/)
-   -   problem using test in cron (https://www.linuxquestions.org/questions/ubuntu-63/problem-using-test-in-cron-4175574174/)

mfoley 03-06-2016 11:47 PM

problem using test in cron
 
This is probably something simple ...

I have the following crontab entry:

Code:

* * * * mon /bin/bash -c "test $(date +%d) -le 07 && echo yup >>/root/yup.log 2>&1"
It is suppose to test that the current day of the month is <= 7th and do the `echo`, on monday.

The command `test $(date +%d) -le 07 && echo yup` works just fine at a command prompt, but in the crontab I get an error email:

/bin/sh: 1: Syntax error: end of file unexpected (expecting ")")

I've stared at this for a long time and can't for the life of me see what's wrong. I'm also a bit confused about the "/bin/sh" bit because I'm explicitly specifying /bin/bash.

Changing to:

Code:

* * * * mon /bin/bash -c "if [ `date +%d` -le 07 ]; then echo yup; fi >>/root/yup.log 2>&1"
(or /bin/date) give the error: "/bin/sh: 1: Syntax error: EOF in backquote substitution"

Note that I am using this cron on Ubuntu 15.10. The crontab entry as initially shown works fine on Slackware.

TenTenths 03-07-2016 05:18 AM

Couple of suggestions:

The use of backtick `` is deprecated, $() is the preferred methodology
Rather than try to write your script as a one-liner in the cron you may find it's better to just have a bash script that does all your tests etc. That way you can expand it much more easily.

wpeckham 03-07-2016 05:20 AM

Personally, if I require conditionals (very common, last day of month, first week of month on wednesday, etc.) I write a small script and CALL it from cron, or call a conditional script and
Quote:

&&
between it and the action.

1. Check, and see if /bin/sh really happens to be bash in disguise. If so stop explicitly calling bash and try just the command. Although it is in posix mode, most built-in and extensions work the same.

2. Try using
Quote:

if [ .. ] ; then ... fi
instead of
Quote:

test
and see if that works better.

onebuck 03-07-2016 08:16 AM

Moderator response
 
Moved: This thread is more suitable in <Ubuntu> and has been moved accordingly to help your thread/question get the exposure it deserves.

Requested by OP

rknichols 03-07-2016 08:38 AM

The "%" sign is special in a crontab and needs to be escaped with a backslash to be treated as a regular character.
Code:

* * * * mon /bin/bash -c "test $(date +\%d) -le 07 && echo yup >>/root/yup.log 2>&1"
                                      ^


mfoley 03-07-2016 11:27 PM

Quote:

Originally Posted by TenTenths (Post 5511521)
Couple of suggestions:

The use of backtick `` is deprecated, $() is the preferred methodology

If you'll notice in my original example I did use $(). Given the error 'Syntax error: end of file unexpected (expecting ")")', I thought the parenthesis might be an issue and I changed to `` to test that.

Quote:

Rather than try to write your script as a one-liner in the cron you may find it's better to just have a bash script that does all your tests etc. That way you can expand it much more easily.
In reality, I am using a script. My "echo yup" is a test stand-in. The test is simply determining when the script should run which, I think, is the job of a crontab entry.

Quote:

Originally Posted by wpeckham (Post 5511521)
Personally, if I require conditionals (very common, last day of month, first week of month on wednesday, etc.) I write a small script and CALL it from cron, or call a conditional script and

Quote:

&&
between it and the action.

Well, that's essentially what I'm doing with the &&. As I said in response to TenTenths, my "echo yup" is a test stand-in for the actual script. I have always commonly done the when-to-run logic in the crontab itself, not the called script -- and I want the same NOW!

Quote:

1. Check, and see if /bin/sh really happens to be bash in disguise. If so stop explicitly calling bash and try just the command. Although it is in posix mode, most built-in and extensions work the same.
Hmmm, on this Ubuntu system /bin/sh is slinked /bin/dash -- whatever that is. However, your point is worth some experimentation.

Quote:

2. Try using
Quote:

if [ .. ] ; then ... fi
instead of
Quote:

test
and see if that works better.
Perhaps you didn't read the WHOLE posting. That's exactly what I show in my 2nd example where I say "Changing to:".

Quote:

Originally Posted by rknichols (Post 5511521)
The "%" sign is special in a crontab and needs to be escaped with a backslash to be treated as a regular character.

Code:

* * * * mon /bin/bash -c "test $(date +\%d) -le 07 && echo yup >>/root/yup.log 2>&1"
^

rknichols - that did the trick! Works like a charm now. thanks.

Interesting that the Slackware cron does not require % to be escaped.

rknichols 03-08-2016 10:29 AM

Quote:

Originally Posted by mfoley (Post 5511940)
Interesting that the Slackware cron does not require % to be escaped.

Slackware uses "Dillon's lightweight cron daemon", which does not support some of the features of other cron daemon implementations, such as the use of the "%" sign to provide data on stdin to the command. Quote from `man 5 crontab`:
The "sixth" field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline or % character, will be executed by /bin/sh or by the shell specified in the SHELL vari- able of the cronfile. 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, the reason that the complaint came from "/bin/sh" is that the command line is first passed to the shell specified at the top of the crontab, so what it saw was a command to invoke /bin/bash with some arguments:
Code:

/bin/bash -c "test $(date +
Unsurprisingly, it didn't like that truncated command line.

A.Thyssen 03-11-2016 12:38 AM

I typically I have cron test the day of month, and than the shell test the day of week.

Also it is run in sh. BUT remember this may not be BASH, so using backtic while depreciated is recommended.

Code:

  0 0 1-7 * * [ `date '+\%u'` -eq 1 ] && CMD
NOTE do not just use '*' in the first two columns That means cron will run it EVERY MINUTE on the days selected
The above will only attempt to run 7 times every month.


All times are GMT -5. The time now is 08:57 PM.