bash : Make job every x days - bash

I have a bash script runned every day via cron.
In this bash I want to run some command but only every x day (x is fixed and will be 3, 4 or 5 I don't know at the moment)
I can test if the remainder of the division day of month / x equal 0
day_of_month % x = 0
I will work on a single month but not always between to month, for example months april - may with x = 3
1 2 3 4 5 6 7 8 9 ... 27 28 29 30 31 1 2 3 4 5 6 7 8 9 ... 27 28 29 30
x x x ... x x x x x ... x x
It not a big deal, but is there any other way to do this ?
PS : I don't want to explode my script and make 2 cron jobs (one every day : *, the other evevery x day : */x)

One easy solution would be to use "day of year" instead of day of month. Then there'd be no problem with different month lengths. You'd still get problems at the end of year, of course.
The "day of year" is available via date +%j.
If that is still not acceptable, you can use the seconds since 1970 (date +%s), and divide by days*24*60*60, then use the remainder of that. You'd still get problems with leap seconds, but otherwise it should be correct.

Using cron sounds the like the proper idea actually, because that is what cron is made for.
One idea though to solve your 'across months' problems: don't think in months, instead check whether the time-in-seconds-since-epoch % x*seconds-per-day is 0 ...

I would export a system variable with last date of execution and calculate the interval from it. It wouldn't work after a restart but I assume in this case the interval should be restored.

Have a look at the at command
Using that you can tell a script to call itself at a later date.
From manpage:
For example, to run a job at 4pm three
days from now, you would do at
4pm + 3 days, to run a job at 10:00am on July 31, you would do at
10am
Jul 31 and to run a job at 1am tomorrow, you would do at 1am
tomorrow.

If I had this problem, I would tell cron to run my script once every day, and inside the script I would calculate whether or not work needs to be done. That way, you have full control over it.
For example,
dayno=`date +%d`
let divided=daynum%3
if [ $divided == 0 ] ; then
exit 0
fi
# real work begins here
This script would work on any system that uses bash.

Does your job need to run every day? That is, does it do something on those days when your calculation does not result in a 0. If not, you could set up a job in cron thus:
0 12 3,6,9,12,15,18,21,24,27,30 * * <your job>
and it would run every third day (at 12 noon in my example).
I'm pretty sure that "Feb 30" would be safely ignored.

Related

Power Automate Recurrence Trigger : how to find last 5 working days of the month?

I need to create a recurrence in Power Automate so that it only runs in the last 5 working days of the month. I can't use a generic rule because months like February are different.
What I have done so far was using a similar recurrence that finds the last working day of the month but need help with optimising it for the last 5 working days instead.
The logic is that the flow runs every day and looks at the first day of the next month, then comes backwards to find the first working day and excludes Monday-Sunday. however, I need it to find the last 5 working days instead of 1.
Also the functions used are like this:
startOfMonth(addToTime(variables('Date'),1,'Month'))
addDays(variables('DateCountDown'),-1)
dayOfWeek(variables('DateCountDown'))
#and(not(equals(variables('DayOfWeek'), 0)), not(equals(variables('DayOfWeek'), 6)))
addDays(variables('DateCountDown'), -1)
dayOfWeek(variables('DateCountDown'))
disclaimer: I am not a pro user of power automate and found this flow in an old GitHub repository (written by Michael Ziemba) - thanks all for your help.
in response to teylin:
I get today (as before)
I get first day of next month (as before)
I go 7 days down now > addDays(variables('DateCountDown'),-7)
I initialize a variable to find week day > dayOfWeek(variables('DateCountDown'))
then varCounter variable as you said (varCounter > integer > 1)
then DO UNTIL loop until varCounter = 7
inside the loop I have 3 conditions: day of week <> 0 , dayof week <> 6 and formatDateTime(variables('DateCountDown'), 'dd-MM-yyyy') = formatDateTime(variables('Date'), 'dd-MM-yyyy') (to check today)
then trigger my stuff if yes,
increment varCounter by 1
Don't overthink this. Conceptually:
Get the first day of the next month (you already know how to do this)
get DayX by subtracting 7 from that date (you already do this with 1, now do it with 7)
By definition, 2 of the seven days between that DayX and the next month will be on a weekend. So, next, you start a loop that runs 7 times. Inside the loop, you have these actions:
add a condition with the following two checks
check if DayX is a weekday (you already know how to do this) AND
check if DayX is = today
In the Yes branch of the condition run the steps that you want to run on the last 5 weekdays, in the No branch do nothing
below the condition step, increment DayX by one day
loop
For the loop, first initialise a counter variable to the value 1. Add a Do Until action and set it to run until the counter is greater than 7. Inside the loop, do your calculations and your condition etc. As the last step of the loop, increment the counter variable by 1.

Cron schedule a task alleatory in a range of hours

I want schedule with cron a task to be ran ONCE in between a certain tange of hours, not every hour in a range.
Example:
I want it may run ONCE between 9 to 12 hours, single time.
Better if I can run the task ONCE between 9 to 12 hours and random minute as well. I don't want can be predictable, but I want keep control about in which range of hours it will be fired.
I tried:
# m h dom mon dow command
00-59 09-12 * * 2 /home/osmc/play.sh
But it ran every minute, between 00 and 59, for every hour between 9 to 12 (not desired)
Any idea how I can do so?
If you like to stick with cron, you could do the following:
0 9 * * 2 sleep $(( RANDOM \% 10800)); /home/osmc/play.sh
The job will start at 9AM, and delays the script for upto 10800 seconds, which is 3 hours.
Another solution found here:
Cron jobs and random times, within given hours

CRON: Run job on particular hours

I have a spring batch application and i am using CRON to set how often this application runs. But the problem i am running into is that i want to run the job on specific hours
3 am
7 am
11 am
3 pm
7 pm
11 pm
As you can see it is every 4 hours but starts at 3 am so i cannot use */4 in the hours section of the timing format as this would start the job at 4am
I have also tried '3,7,11,15,19,23' in the hours section but this does not work either (guessing it only works in the minutes section). Does someone know how i can do this?
Use
#Scedule(cron="0 0 3/4 * * ?")
The Pattern x/y means: where <timepart> mod y = x
or
#Scedule(cron="0 0 3,7,11,15,19,21 * * ?")
According to the Quartz Cron Trigger Tutorial:
The '/' character can be used to specify increments to values. For
example, if you put '0/15' in the Minutes field, it means 'every 15th
minute of the hour, starting at minute zero'. If you used '3/20' in
the Minutes field, it would mean 'every 20th minute of the hour,
starting at minute three' - or in other words it is the same as
specifying '3,23,43' in the Minutes field. Note the subtlety that
"/35" does *not mean "every 35 minutes" - it mean "every 35th minute
of the hour, starting at minute zero" - or in other words the same as
specifying '0,35'.
0 0 3,7,11,15,19,23 * * ?
Fires for 0 minute starting at 3am and ending at 23:00 pm every day.
judging by the two answers above the error i was making was i was keeping the apostrophe at the start and end of my hours... very silly
i managed to solve this by using 3-23/4 for the hour as this starts from 3am and then every other fourth hour (just a different way of doing it to the other answers)

Relation Duration x Work x Start Date x End Date in MS Project 2007

Well, i'm beginner in MS Project (specifically in MS Project 2007) and a i got the following problem:
1 - I have all tasks maped in "Grantt Charts".
2 - My workday is 14 hours per week (monday to monday, without holidays).
3 - The work schedule is from 21:00PM to 23:00PM, so calculating this we have:
(2h per day) X (7 days in a week) = 14h per week.
The big problem is: When i put 7 days in column durating (in any task) the work shows 14h (this is correct) but the start date and end date just count 1, my ideia is that for MS PROJECT 1 day have 8h of work (and not 2h as i wanna), so 14h is like 1,75 days, but should be exact 7 days because my project is like that, only 2h per day and not 8h per day as MS PROJECT think.
There is an independant setting in MS-Project that tells the system how many hours you consider there to be in a working day. In your case it should be 2, not the default of 7.
Go to "Change Working Time" on the Tools menu. Click the "Options" button. Change the field entitled "Hours per day" to 2.

VBS login script using between time ranges

I need to run a vbs script at login that will run a batch script based on a time range of between 22:00 and 06:00 the following day.
I have the current script as follows
If Hour(Now()) >= 20 AND hour(Now()) < 6 Then
//RUN SCRIPT
Else
//RUN OTHER SCRIPT
End If
Now the script runs fine when I use pre noon times e.g 6 and 11 but the about it does not. I can see the issue in that is is not factoring in the following days time and actually going back in time. What I need is the following
if time is 20:00 on day 1 but less than 06:00 on day 2 run the script else run the other script
This needs to run continuously between these times for every day of the week.
Please can you help?
Why not just change AND to OR? In that case when the hour of the day is greater than 20 then it will fire. if the hour of the day is less than 6 it will also fire. Look at it less of the time frame when it needs to fire and more of a time frame excluding those hours when it does not need to fire.
If Hour(Now()) >= 20 OR hour(Now()) < 6 Then
//RUN SCRIPT
Else
//RUN OTHER SCRIPT
End If
VB Script Date Functions

Resources