Questions

Forum Navigation
Please to create posts and topics.

Cron jobs without specifying hour/day/month.....

Is there a way to create cron jobs, using crontab in Linux, without specifying hour/day/month, for example, but using a general "daily" or "monthly" words?

Yes, there is a way to use a special approach to define a periodic cron job in Linux.

If we take a look inside the /etc directory, we can see directories like cron.hourly, cron.daily, cron.weekly and cron.monthly, each corresponding to a certain frequency of execution. One way to schedule our tasks is to place our scripts in the proper directory but, in addition to this way, some cron implementations may support some special strings. These strings are used instead of the first five fields, each specifying a certain frequency:

@yearly, @annually Run once a year at midnight of January 1 (0 0 1 1 *)
@monthly Run once a month, at midnight of the first day of the month (0 0 1 * *)
@weekly Run once a week at midnight of Sunday (0 0 * * 0)
@daily Run once a day at midnight (0 0 * * *)
@hourly Run at the beginning of every hour (0 * * * *)
@reboot Run once at startup

For example, we can schedule a job to run everyday as follows:

@daily sh /root/script.sh

Usually, @daily, @hourly, @weekly and @monthly are set by default to specific time periods. Using the run-parts command we can find out when each keyword will be executed (the values are taken from the /etc/crontab file); the following output has been taken from a Debian/Ubuntu system:

[email protected]:~# grep run-parts /etc/crontab
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

So, on Debian/Ubuntu systems:

  • cron.daily run once at every hour at 1:17am, 2:17am, 3:17:am … 1:17pm.
  • cron.daily run once at every day at 6:25am.
  • cron.weekly run once at every day at 6:47am.
  • cron.monthly run once at every day at 6:42am.

Sometimes it may be good to schedule a cron job to run at a somewhat random time: generally not truly random, but maybe at an arbitrary time within a specified time range rather than at a specific recurring interval.

This can be useful to keep simultaneous cron jobs for different users from causing predictable spikes in resource usage, or to run at a time other than the start of a new minute, since cron’s interval resolution doesn’t go smaller than one minute.

A first way in applying a random offset to a specific cron jobs could be the following, where the job will wait for a random time between 0 and 600 seconds (= 10 minutes), the $(( RANDOM \% 600 )) part, before running your job:

@reboot sleep $(( RANDOM \% 600 )); /path/to/executable

NOTE: the % character need to be escaped when used in cron, so you have to write \% in the cron job (as shown below).

Another way, for example, is to use Perl instead of bash:

@reboot perl -e 'sleep(rand(3000))'; /path/to/executable

Another way to introduce a random amount of time is combination of sleep and numrandom with a time range between 0 and 30 minutes, for example.

@reboot sleep `numrandom /0..30/`m ; /path/to/executable

In order to use the numrandom command, we need to install num-utils, on Debian, by using apt-get -y install num-utils.

Other two a bit more complex examples would be the following; the first below shows how to define a random time, between 3 and 5 minutes, to a specific cron job. The */3 * * * * means "each 3 minutes", while thet0to180secs is a variable that will represent a random value between 0 and 181 and it will be used by the sleep command (sleep ${r}s) as parameter to wait a specific amount of seconds (in addition to the base 3 minutes):

t0to180secs="RANDOM % 181"
*/3 * * * * r=$(($t0to180secs)) ; sleep ${r}s; echo date

The second example shown below use a similar approach of the above, but used to specify a random day of the week at midnight (00 00 * * 0); in this case, the random value will be between 0 and 6 and the sleep command will force the specific cron job to wait 0 to 6 days before running (sleep ${r}d):

tday0_to_day6="RANDOM % 6"
00 00 * * 0 r=$(($tday0_to_day6)) ; sleep ${r}d; echo date

NOTE: obviously the above two examples can be used also with @monthly, @daily or @reboot special strings.