Add a job to cron and execute every 1h and x mins - cron

I would like to execute a cronjob every 1 hour and x mins
I tried adding to crontab:
*/53 */1 * * * /myscrop.sh
But the scrip is executed every 53 mins and not 1h and 53 mins

With "regular" crontab entries, this is rather difficult to do without a large number of them.
Since you want your job to happen every 1h:53m (113m), you may just be able to run every minute but with a suitable step value, something like:
*/113 * * * command-to-run
although I've never tested this with large skip values like that.
If that works, it's probably the easiest solution.
If you're running in an environment where that doesn't work, you can revert to the trick of actually running the script every minute but having it decide whether or not it does the actual "payload" of the task.
To do this, use a state file to record the last time the payload was run. Though the script itself runs very often, the payload only runs when enough time since the last has passed.
For example, the following script only runs the payload (the final echo) every seven seconds, regardless of how often the script is called:
#!/bin/bash
# Configuration items.
stateFile=/tmp/lastPayload # File holding time of last payload run.
minGap=7 # How often payload should run (seconds).
# Get last payload time (checks for non-valid data).
((lastTime = 0))
[[ -f ${stateFile} ]] && lastTime="$(cat ${stateFile})"
[[ "${lastTime}" =~ [1-9][0-9]* ]] || ((lastTime = 0))
# Exit if not enough time since last payload run.
thisTime=$(date +%s)
((timeGap = thisTime - lastTime))
[[ ${timeGap} -lt ${minGap} ]] && exit
# Update last payload run time and execute payload.
echo ${thisTime} >${stateFile}
echo "[${lastTime}] [${thisTime}] [${timeGap}]"
If that script is called test_periodic.sh, you can test it with:
while true ; do ./test_periodic.sh ; sleep 1 ; done
This will run it every second but you'll notice the payload is only done every seven seconds (other than the first time), as expected:
[0] [1504041523] [1504041523]
[1504041523] [1504041530] [7]
[1504041530] [1504041537] [7]
[1504041537] [1504041544] [7]
For 1h:53m, set minGap to be 6780 (113 minutes, in seconds) and have cron run the script every minute.

Cron doesn't add the hours and minutes for the interval. */53 */1 * * * runs at 1:53, 2:53, 3:53, etc.
You'd have to create separate schedules. For a 53 minute interval, the set would look as follows:
0 0 * * * /myscrop.sh
53 0 * * * /myscrop.sh
46 1 * * * /myscrop.sh
39 2 * * * /myscrop.sh
32 3 * * * /myscrop.sh
25 4 * * * /myscrop.sh
18 5 * * * /myscrop.sh
11 6 * * * /myscrop.sh
4 7 * * * /myscrop.sh
57 7 * * * /myscrop.sh
50 8 * * * /myscrop.sh
43 9 * * * /myscrop.sh
36 10 * * * /myscrop.sh
29 11 * * * /myscrop.sh
22 12 * * * /myscrop.sh
15 13 * * * /myscrop.sh
8 14 * * * /myscrop.sh
1 15 * * * /myscrop.sh
54 15 * * * /myscrop.sh
47 16 * * * /myscrop.sh
40 17 * * * /myscrop.sh
33 18 * * * /myscrop.sh
26 19 * * * /myscrop.sh
19 20 * * * /myscrop.sh
12 21 * * * /myscrop.sh
5 22 * * * /myscrop.sh
58 22 * * * /myscrop.sh
51 23 * * * /myscrop.sh
And note that the interval always restarts at the beginning of the day.

Related

How do I write a CRON expression to trigger a job every 90 seconds?

I have scheduled a web job to run every minute using this "0 * * * * * CRON expression. It is running as expected. Then I changed the CRON expression from 0 * * * * * to */90 * * * * * to make it run every 90 seconds. But it is not running every 90 seconds.
How do I write a CRON expression for running a web job every 90 seconds?
You can split it into two seperate CRON expressions:
Running every three minutes on even minutes.
0 */3 * * * *
Running every three minutes on uneven minutes starting on the 30th second.
30 1-59/3 * * * *

Why sed is duplicating the first added line (sending the sed output to the same file)?

Starting file (/etc/crontabs/root):
# do daily/weekly/monthly maintenance
# min hour day month weekday command
*/15 * * * * run-parts /etc/periodic/15min
0 * * * * run-parts /etc/periodic/hourly
0 2 * * * run-parts /etc/periodic/daily
0 3 * * 6 run-parts /etc/periodic/weekly
0 5 1 * * run-parts /etc/periodic/monthly
I want to replicate this file, remove comments... and adding the content to the same file, so I run:
sed '/^#/ d; s/\/etc/\/root\/etc/' /etc/crontabs/root >> /etc/crontabs/root
... which should remove all comments, replace /etc with /etc/root... and add the result to the same file.
Wrong output (please note the "extra" line starting with */15):
# do daily/weekly/monthly maintenance
# min hour day month weekday command
*/15 * * * * run-parts /etc/periodic/15min
0 * * * * run-parts /etc/periodic/hourly
0 2 * * * run-parts /etc/periodic/daily
0 3 * * 6 run-parts /etc/periodic/weekly
0 5 1 * * run-parts /etc/periodic/monthly
*/15 * * * * run-parts /root/etc/periodic/15min
0 * * * * run-parts /root/etc/periodic/hourly
0 2 * * * run-parts /root/etc/periodic/daily
0 3 * * 6 run-parts /root/etc/periodic/weekly
0 5 1 * * run-parts /root/etc/periodic/monthly
*/15 * * * * run-parts /root/root/etc/periodic/15min
Expected/wanted output:
# do daily/weekly/monthly maintenance
# min hour day month weekday command
*/15 * * * * run-parts /etc/periodic/15min
0 * * * * run-parts /etc/periodic/hourly
0 2 * * * run-parts /etc/periodic/daily
0 3 * * 6 run-parts /etc/periodic/weekly
0 5 1 * * run-parts /etc/periodic/monthly
*/15 * * * * run-parts /root/etc/periodic/15min
0 * * * * run-parts /root/etc/periodic/hourly
0 2 * * * run-parts /root/etc/periodic/daily
0 3 * * 6 run-parts /root/etc/periodic/weekly
0 5 1 * * run-parts /root/etc/periodic/monthly
Ideas?
You shouldn't write out to the same file that you're reading from. It will read the lines that you added to the file, and continue processing them. So when it gets to the lines with /root/etc, it will replace the /etc in that, producing /root/root/etc. It could conceivably get stuck in an infinite loop, since it keeps extending the file and will never reach the end.
What you can do is copy the crontab file to a new file, then use sed to append to that.
cp /etc/crontabs/root /tmp/new_crontab
sed '/^#/ d; s/\/etc/\/root\/etc/' /etc/crontabs/root >> /tmp/new_crontab
cp /tmp/new_crontab /etc/crontabs/root
If you want a one liner, it's fairly straightfoward using ed:
printf "%s\n" ka '1,$t' "'a,\$g/^#/d" "'a+1,\$s/\/etc/\/root\/etc/" w | ed -s /etc/crontabs/root
or a bit easier to read using a heredoc:
ed -s /etc/crontabs/root <<'EOF'
ka
1,$t
'a,$g/^#/d
'a+1,$s/\/etc/\/root\/etc/
w
EOF

How to make crontab execute every 2 hours between 10am and 10pm?

I need my crontab to execute every 2 hours starting at 10am and the last one running at 10pm.
I currently have
0 */2 * * * /directory/job.sh
How do I block out the hours I don't want?
Thanks!
0 10/2 * * * /directory/job.sh would do it.
0 10-22/2 * * * /directory/job.sh would do it and be more explicit.
0 10,12,14,16,18,20,22 * * * /directory/job.sh would do it, too.

Set Cronjob to Run Every 5 Minutes From 9:30am to 4:00pm

I need to set a cronjob to run a bash script every 5 minutes, starting at 9:30am until 4:00pm.
I have the following but, it's not quite right...
Cronjob:
*/5 9-16 * * * /path/to/directory/job.sh > /path/to/log/file/job.log 2>&1
What you have there is a line that will run the command every five minutes between 09:00 and 16:55 (all ranges here are inclusive).
What you're trying to achieve can be done relatively simply with three separate crontab lines:
30-59/5 9 * * * /path/to/directory/job.sh > /path/to/log/file/job.log 2>&1
*/5 10-15 * * * /path/to/directory/job.sh > /path/to/log/file/job.log 2>&1
0 16 * * * /path/to/directory/job.sh > /path/to/log/file/job.log 2>&1
The first handles the case between 09:30 and 09:55, the second every five minutes between 10:00 and 15:55, and the final one the single job at 16:00.
Cron doesn't have a syntax for expressing that directly, so you'll need 3 separate lines: one for 9:30-9:55, one for 10:00-15:55, and one for 16:00.
I think this is correct:
30-55/5 9 * * * <command>
*/5 10-15 * * * <command>
0 16 * * * <command>

Run Cron job every N minutes plus offset

*/20 * * * *
Ensures it runs every 20 minutes, I'd like to run a task every 20 minutes, starting at 5 past the hour, is this possible with Cron? Would it be:
5/20 * * * * ?
To run a task every 20 minutes starting at 5 past the hour, try this:
5-59/20 * * * *
Explanation
An * in the minute field is the same as 0-59/1 where 0-59 is the range and 1 is the step. The command will run at the first minute in the range (0), then at all successive minutes that are distant from the first by step (1), until the last (59).
Which is why */20 * * * * will run at 0 minutes, 20 minutes after, and 40 minutes after -- which is the same as every 20 minutes. However, */25 * * * * will run at 0 minutes, 25 minutes after, and 50 minutes after -- which is not the same as every 25 minutes. That's why it's usually desirable to use a step value in the minute field that divides evenly into 60.
So to offset the start time, specify the range explicitly and set the first value to the amount of the offset.
Examples
5-59/20 * * * * will run at 5 minutes after, 25 minutes after, and 45 minutes after.
10-59/25 * * * * will run at 10 minutes after and 35 minutes after.
1-59/2 * * * * will run every odd minute.
Sure!
5,25,45 * * * * /your/cron
You can try: */5 * * * * sleep N; your job

Resources