Let's say I wanted to run a cronjob in a random interval, for example, every 3 to 5 minutes. Or every 1 to 20 minutes. Or some other random interval. It's not hard, lemme show you...
But first, let's talk about editing your crontab. Every user has their own crontab file where each configured line says "run this command on this date and time". There are several ways to work with cron, but a user's crontab is the most straight-forward mechanism.
Working with cron is this process:
Edit crontab ⟶ Save ⟶ Exit ⟶ Changes applied
Changes do not take effect until after you exit the editor.
You edit your personal crontab configuration file with a specially built
workflow process. To edit with, open up a terminal and type crontab -e
. Then you make your changes and
save+exit.
Note: crontab usually uses
vi
as its editor, or whatever the EDITOR environment variable is set to. If you don't like the default choice, use a different one with, for example,EDITOR=vim crontab -e
orEDITOR=gedit crontab -e
orEDITOR=nano crontab -e
orEDITOR=micro crontab -e
or whatever.
Crontab executes things on a schedule. Every line in the crontab file represents a scheduled event. You CANNOT split things between lines. They all operate asynchronous to each other. If you want to do something really really complicated, write a script instead, and then execute that script from your crontab.
The format: I am not going to go into great detail here —read man 5 crontab
instead— but
the general format of a crontab entry line is:
mins hours day-of-month month day-of-week command-or-script
For example, I want to send the date to a log file every minute...
* * * * * date >> $HOME/crontab-demo.log 2>&1
Each of those *
's means "every" -- every minute, hour, day-of-month, etc...
For these examples, open another terminal and watch the demo logfile we are creating:
tail -F ~/crontab-demo.log
When this exercise is over,
CTL-C
to exit and feel free to delete the logfile.
For example, if I wanted to write the current date and time to a log file every 3 minutes...
*/3 * * * * date >> $HOME/crontab-demo.log 2>&1
...or at 3am and 5am...
* 3 * * * date >> $HOME/crontab-demo.log 2>&1
* 5 * * * date >> $HOME/crontab-demo.log 2>&1
...but since they were the same command, the syntax could be...
* 3,5 * * * date >> $HOME/crontab-demo.log 2>&1
How would I make it execute randomly every 3 to 5 minutes?
For this example, we also demonstrate using a logfile variable. Note, the
present working directory is $HOME (your home directory), but you can't use
$variables except on the commandline. Therefore, in this example, if we
redirect to just $logfile, it will write to $HOME/$logfile.
logfile=crontab-demo.log
t0to120secs="RANDOM % 121"
*/3 * * * * r=$(($t0to120secs)) ; sleep ${r}s ; date >> $logfile 2>&1
How would I execute a command at a random day of the week at midnight?
logfile=crontab-demo.log
tday0_to_day6="RANDOM % 6"
00 00 * * 0 r=$(($tday0_to_day6)) ; sleep ${r}d ; date >> $logfile 2>&1
How about that random 3 to 5 minutes example, but with MUCH fancier logging?
logfile=crontab-demo.log
m0="-- Job scheduled -- pid:"
m1="-- Job started ---- pid:"
m2="-- Job completed -- pid:"
# date formatting...
df="%b %d %T UTC"
t0to120secs="RANDOM % 181"
*/3 * * * * { date --utc +"$df $m0 $$" && r=$(($t0to120secs)) ; sleep ${r}s ; date --utc +"$df $m1 $$" && date && echo "Hello there!" --utc +"$df $m2 $$" ; } >> $logfile 2>&1
The result would looks something like this...
[taw00@demo ~]$ tail -F crontab-demo.log
Feb 26 15:51:01 UTC -- Job scheduled -- pid: 17144 (sleeping for 94s)
Feb 26 15:52:35 UTC -- Job started ---- pid: 17144
Hello there!
Feb 26 15:52:35 UTC -- Job completed -- pid: 17144
If you want to watch cronjobs kicking off in the journal logs, do this...
journalctl /usr/sbin/crond |tail -n100
# ...or...
journalctl /usr/sbin/crond -f
Do that as root or using sudo
. I leave it to you, dear reader, to learn how
to work with journalctl with a bit more sophistication.
You can either wipe out the examples in your crontab or save them for future refence: Just comment out any schedule lines in your crontab (with #
), save, and exit. You now have a small reference for the next time you have to edit the crontab configuration.
I hope this was of help. Send comments and feedback to [email protected]
Wondering why your cron job is failing and can't quite figure it out? Set up a duplicate environment and test your commandline.
crontab -e
Now add this to your crontab, scheduled for 1 minute after "right now". For example, if it is currently, 14 minutes after midnight, I would schedule this for 00:15...
15 00 * * * env > ~/cronenv
Save and exit.
Wait until 00:15 for that file to show up. And then...
env - `cat ~/cronenv` /bin/sh
Now test your commandline. Your environment is now identical to cron's.