Problem with $RANDOM in crontab
I've got a strange problem with $RANDOM in cron. I wish to execute a command a random number of minutes after the cronjob fires.
This example works directly in the terminal and delays the command up to 30 seconds (replace command with whatever you want, it's actually an echo to /dev/ttyUSB0):
sleep `expr $RANDOM \% 30` ; command
If the same line is placed in crontab, the command always fires immediately without the delay:
* * * * * sleep `expr $RANDOM \% 30` ; command
If I use an expression without $RANDOM, it works fine - this makes a delay of 15 secs:
* * * * * sleep `expr 10 + 5` ; command
In other words, it seems like $RANDOM does not work in a cron.
But it is not simply because $RANDOM itself evaluates to zero, because then this should give a delay of 10:
* * * * * sleep `expr $RANDOM \% 30 + 10` ; command
I have also tried with && instread of ; but that doesn't help. In fact, then the command does not fire at all!
I could of course place the delay in a script which is then called from crontab, but that does not explain my problem and does not make me learn :-)
It's Debian Lenny if that makes any difference.
Solution 1:
cron
uses the /bin/sh
shell to execute tasks. In some distros, this is a symlink to dash
. Neither of them supports the $RANDOM
variable, which is a bash
-specific extension.
With vixie-cron, you can put a line
SHELL=/bin/bash
at the top of your crontab.-
Otherwise, you will have to settle with
bash -c 'echo $RANDOM'
orperl -e 'print int(rand(65535))'
.(In the above example, 65535 is the maximum number to return. You can apply other math inside the script too.)
In a properly configured system, you would have been informed about this by
cron
itself – it always sends job output, including error messages, by email. Install a lightweight MTA.
Also, in bash, $(( ))
is preferred over `expr`
.
Solution 2:
cron
typically runs with a less "full" environment, meaning that you simply don't have many of the same environment variables available to you. Apparently $RANDOM
is one such, and in fact your sleep
command is simply failing with an error because of the undefined variable -- which is why your command failed to run at all when you switched to &&
instead of ;
. (Well, actually, $RANDOM
is a Bash function, but cron
doesn't run in a full Bash environment, which evidently lacks this function.)
To accomplish this task, you will need to use a separate Bash script, as you said. Alternatively, you might be able to figure out a way to use cat /dev/urandom
directly in the cron
command, but it would probably be easier just to move what you currently have to a separate Bash script.