Every x days vs every xth day of the month - linux

I have the following cron expression:
0 0 */30 * *
How come it still runs every 30th day of the month and not every 30 days starting from now? Having the expression:
0 0 30 * *
Yields the same run times:
2013-07-30 00:00:00
2013-08-30 00:00:00
2013-09-30 00:00:00
2013-10-30 00:00:00
2013-11-30 00:00:00

I think you might want to use at instead of cron. You can use at to schedule your script to run 30 days from now with the following:
at now +30 day /path/to/your/script
Then, just put the same line near the end of your script, to schedule it to run again 30 days later.

Related

Need a cron expression

I am trying to get a cron expression through cron convertors online but it won't be able to do the same.
Some please help. I need a cron expression which should run every 3 hours starting at 00:10.
00:10
03:10
06:10
...
Also I need a cron expression that runs every 30 mins starting from 00:00.
00:00
00:30
01:00
...
something like this^
I tried
10/3 * * * *
and
*/30 * * * *
I need a cron expression which should run every 3 hours starting at
00:10
Simply with
10 0/3 * * * your_command
This way, the cron will run the specified command at 10 minutes past midnight (10 0) and then every 3 hours thereafter (0/3)
Also I need a cron expression that runs every 30 mins starting from
00:00
Then this might do the work
0,30 0-23/1 * * * /path/to/command
So it will run at 00:00 and 00:30 every day (0,30), every hour (0-23/1), and regardless of the day of the month, month, or day of the week (*)

Running a cron at 4 am and 4 pm

The following cron expression cron(0 14 ? * MON-FRI *) basically runs something 4:00 pm from Monday to Friday.
I am wondering if it is possible to modify the expression so I can run something at 4:00 am and 4:00 pm every Monday to Friday.
Use this crontab line to run command_name at 4:00 and 16:00 (4 AM and 4 PM) Monday-Friday:
0 4,16 * * 1-5 command_name
From crontab manual:
The time and date fields are:
field allowed values
----- --------------
minute 0-59
hour 0-23
day of month 1-31
month 1-12 (or names, see below)
day of week 0-7 (0 or 7 is Sunday, or use names)
Your Cron job description looks different from the general crontab. But to give you an idea of how to achieve what you're looking for:
Edit cron-table. Choose your editor.
crontab -e
Add 2 lines cron jobs.
* 4 * * 1-5 /usr/bin/...# Your command goes here 04:00 am.
* 16 * * 1-5 /usr/bin/...# Your command goes here 04:00 pm.
4PM (16:00): 0 16 * * MON-FRI
See crontab guru
"At 16:00 on every day-of-week from Monday through Friday.”
4AM &4 PM (4:00 & 16:00): 0 4,16 * * MON-FRI
See crontab guru
β€œAt minute 0 past hour 4 and 16 on every day-of-week from Monday through Friday.”

Set a cron every 10 days starting from 16th January

How to set a cron to execute every 10 days starting from 16th January? Would this suffice?
30 7 16-15/10 * * command >/dev/null
The above starts at 7.30 AM, 16th of every month and ends on next month 15th and repeats every 10 days. I don't think what I have above is correct. Can anyone tell me how to set up the cron so that month ends are taken into account and every 10 days the command is executed starting from 16th January this year 2016?.
As William suggested, cron can't handle this complexity by itself. However, you can run a cron job more frequently, and use something else for the logic. For example;
30 7 16-31 1 * date '+\%j' | grep -q '0$' && yourcommand
30 7 * 2-12 * date '+\%j' | grep -q '0$' && yourcommand
This date format string prints the day of the year, from 001 to 365. The grep -q will do a pattern match, NOT print the results, but return a success of a failure on the basis of what it finds. Every 10 days, the day of the year ends in a zero. On those days, yourcommand gets run.
This has a problem with the year roll-over. A more complex alternative might be to do a similar grep on a product of date '+%s' (the epoch second), but you'll need to do math to turn seconds into days for analysis by grep. This might work (you should test):
SHELL=/bin/bash
30 7 * * * echo $(( $(date '+%s') / 86400 )) | grep '0$' && yourcommand
(Add your Jan 16th logic too, of course.)
This relies on the fact that shell arithmetic can only handle integers. The shell simply truncates rather than rounding.
UPDATE
In a comment on another answer, you clarified your requirements:
The command should start executing on January 16th, and continue like on January 26th, February 5th, February 15th and so on – jai
For this, the epoch-second approach is probably the right direction.
% date -v1m -v16d -v7H -v30M -v0S '+%s'
1452947400
(I'm in FreeBSD, hence these arguments to date.)
SHELL=/bin/bash
30 7 * * * [[ $(( ($(date '+\%s') - 1452947400) \% 864000 )) == 0 ]] && yourcommand
This expression subtracts the epoch second of 7:30AM Jan 16 (my timezone) from the current time, and tests whether the resultant difference is divisible by 10 days. If it is, the expression evaluates true and yourcommand is run. Note that $(( 0 % $x )) evaluates to 0 for any value of $x.
This may be prone to error if cron is particularly busy and can't get to your job in the one second where the math works out.
If you want to make this any more complex (and perhaps even if it's this complex), I recommend you move the logic into a separate shell script to handle the date comparison math. Especially if you plan to add a fudge factor to allow for jobs to miss their 1-second window .. that would likely be multiple lines of script, which is awkward to maintain in a single cronjob entry.
Observation: the math capabilities of cron are next to non-existent. The math capabilities of the Unix tools are endless.
Conclusion: move the problem from the cron domain to the shell domain.
Solution: run this each day with 30 7 * * * /path/to/script in the crontab:
#!/bin/sh
PATH=$(/usr/bin/getconf PATH)
if test $(($(date +%j) % 10)) = 6; then
your_command
fi
This tests whether the day-of-year modulo 10 is 6, like it is for January 16 (and January 6th is already in the past...).
Thinking outside the box:
Fix your requirement. Convince whoever came up with that funny 10 day cycle to accept a 7 day cycle. So much easier for cron. This is following the KISS principle.
0 30 7 1/10 * ? * command >/dev/null
Output for the above express is,
Saturday, January 16, 2016 7:30 AM
1. Thursday, January 21, 2016 7:30 AM
2. Sunday, January 31, 2016 7:30 AM
3. Monday, February 1, 2016 7:30 AM
4. Thursday, February 11, 2016 7:30 AM
5. Sunday, February 21, 2016 7:30 AM
Output for your expression
i.e 30 7 16-15/10 * * command >/dev/null
2016-01-15 07:30:00
2016-02-15 07:30:00
2016-03-15 07:30:00
2016-04-15 07:30:00
2016-05-15 07:30:00
2016-06-15 07:30:00
2016-07-15 07:30:00
2016-08-15 07:30:00
2016-09-15 07:30:00
2016-10-15 07:30:00
The closest syntax would like this:
30 7 1-30/10 * *
30 7 1-31/10 * *
30 7 1-28/10 * *
30 7 1-29/10 * *
You can test the cron expression here http://cron.schlitt.info/

Scheduling scripts with variable frequency

I want to run a python script on a ubuntu 14.04 server with following frequency:
Monday to Friday:
From 0800 hrs to 1600 hrs: Run once every hour
From 1600 hrs to 2300 hrs: Run once every 30 minutes
Saturday and Sunday:
From 0800 hrs to 2300 hrs: Run once every two hours
At other times, don't run
Is this possible with cron? If not, can anybody suggest some alternative?
As suggested in the comments, adding these cron entries will do:
(Lines starting with # are comments)
# monday to friday, 8 am to 4 pm, once every hour
0 8-16 * * 1-5 <command>
# monday to friday, 4 pm to 10 pm, twice every hour
0,30 17-22 * * 1-5 <command>
# saturday to sunday, 8 am to 11 pm, once every hour
0 8-23 * * 0,6 <command>

Running a cron job every 2:30 on every day?

If I creating cronjob to running for every 2:30 the command will run? (It mean, my cron will running after 90 minutes for every hours.)
the command like: 30 */2 * * * /command/xxx => that's right?
Please help?
Your cron expression 30 */2 * * * will run the command every 2 hours at 30 mins past the hour i.e.00:30, 02:30, 04:30, 06:30 and so on.
If you want to run your command at intervals of two and a half hours i.e. 00:00, 02:30, 05:00, 07:30 and so on, you need to set up two crons:
0 0-20/5 * * * runs at 0 mins past the hour, every 5 hours between 00:00 and 20:00 inclusive i.e. 00:00, 05:00, 10:00, 15:00 and 20:00
30 2-22/5 * * * runs at 30 mins past the hour, every 5 hours between 02:00 and 22:00 inclusive i.e. 02:30, 07:30, 12:30, 17:30 and 22:30
On the other hand, if you want to run your command only once every day at 02:30 use 30 2 * * *.
sudo crontab -e
and then add this:
30 2 * * * /enter/your/command

Resources