How do I get cron to exclude the first day of the month? - cron

At the moment my script runs every day as follows
0 3 * * * wget --timeout=0 http://...
Is there some syntax whereby I can exclude the first day of the month i.e. Jan 1, Feb 1, Mar 1... At the moment I shut down manually each month

You can use
0 3 2-31 * * wget --timeout=0 http://...

Related

Crontab start as half past hour

I got this crontab code to run a script on crontab every 15 minutes from 9 to 18 all days except weekends. However I would like to start fro 9:30 instead of 9. Is it there a way to do it?
*/15 9-18 * * 1-5
Using 30/15 in the minute area should work just fine:
30/15 9-18 * * 1-5
This will instruct crontab to run your script: β€œAt every 15th minute from 30 through 59 past every hour from 9 through 18 on every day-of-week from Monday through Friday.”
I finally did this, and it works
30 9 * * 1-5
45 9 * * 1-5
*/15 10-18 * * 1-5
However, it needs three crontab entries.

Crontab running at unintended times

I am trying to run a script Monday through Friday every 2 hours during working hours (9 am - 4 pm).
I tried this:
0 09-16/2 * * 1-5 /local/bin/script.sh
But now my script runs Monday through Friday from 2 AM to 8 AM. I don't see what's wrong.
Try this
0 9,11,13,15 * * 1,2,3,4,5 /local/bin/script.sh

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/

Every x days vs every xth day of the month

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.

What is the syntax for a cron job that runs 15 and 45 minutes after the hour?

What is the syntax for a cron job that runs 15 and 45 minutes after the hour? (So every 30 minutes.)
Would the syntax be something like:
15,45,30 * * * * wget -O /dev/null http://somesite.com/4_leads.php
So for example it would run at
2:15
2:45
3:15
3:45
4:15
4:45
and so on
From man 5 crontab
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 Sun, or use names)
Or, in other words
# m h dom mon dow user command
15,45 * * * * yourusername wget -O /dev/null http://somesite.com/4_leads.php
Skip the username field if you place the entry in a user specific crontab, via crontab -e, crontab -e -u yourusername, or similar.
This question may be better suited to serverfault.

Resources