Crontab on week numbers - shell

I would like to set a cronjob on certain week numbers. The reason for that, I have a script that should run once a day except of week number 8 and 9. There it should run twice a day.
How can I set a cronjob based on week numbers?

Cron doesn't offer that level of scheduling flexibility, so you have to make your script smarter.
Make your cron job run twice a day, leaving some log file or other artifact that shows it has run. Then have it check whether it's already run that day, and finally also check the week number to see if it's OK for it to run the second time.

Related

Do I have to run cron every minute for Laravel's task scheduler, or is it OK to run less frequently? [duplicate]

This question already has answers here:
Laravel Artisan: How does `schedule:run` work?
(2 answers)
Closed 2 years ago.
I've read the relevant part of the docs and various guides, but I'm unclear as to whether Laravel requires the the cron to be run every minute, or whether it's OK to run less often, i.e. hourly, daily, weekly, etc, without causing issues?
In my case I need a script to run monthly; at the end of each month. It has to run at UTC-12 hours (i.e. the time at which the given calendar month will cease to exist everywhere on earth). Do I really need to run the cron job every minute for this, or does it suffice to run every hour? I would assume running it every hour will be fine without causing issues, but I'd like to confirm this.
Cron can be started at any time. You can "play" with Cron at this site.
If I understand the question correctly, the solution you need: 0 0 1 * *
This is a run at the beginning of each month. This is necessary because the Cron does not know when there are 31 days in a month and when there are 30 or less.
Or you could do something like this: 59 23 28-31 * *, but then the Cron will be triggered every month from the 28th to the 31st.

Task scheduler to run tasks only during the last full workweek of the month

I have multiple tasks that need to be scheduled during the last full workweek (Monday through Friday) of every month. These will be scheduled from a Windows Server 2016 server. I cannot figure out the logic to do it.
Additional info to help:
July 2020 is a perfect month to just say run on the last Monday/Tuesday/etc. Most months will not end with a full workweek though. It may end on a Tuesday and the full workweek ended 4 days before that.
I have ideas of how to do this, but they are not fully formulated:
Find the last Friday of the month and start 4 days before that.
Find the last Monday with at least 4 additional days in the month after.
If the last day of the month is Sunday, start 6 days before that; Saturday, start 5 days before that; etc.
What is the cleanest method to do this in task scheduler? (The scripts being scheduled are in PowerShell, though I don’t think that matters).
So, your situation is: "I have a script, I have a complicated date schedule, and I would like my script to be launched according to that schedule.",
and your question is: "How to perform this scheduling in Windows task scheduler?"
My answer would be:
Don't do it like that, but write a new script which verifies the current date, and verifies if the current date corresponds to the complicate date schedule (in that case, launch your original script), and use Windows task scheduler to launch this new script on a daily basis.
As for making that new script, this URL explains how to perform date handling in Powershell.
This particular use case can actually be done fully in the Task Scheduler.
When adding a new trigger, select Monthly then for Months select <Select all months>. Then, change the radio button below it to Onand chooseLastand`.
May I suggest a solution:
In VBA write a very short Sub routine indicating the current date (using "Now() + 1".
Then use "instr(1,string1,""/"")" to see whether the second entry in the resulting date (such as "5/1/2022") is a "1". If it is, then you can issue a warning on a prepared Notepad.txt the day before the 1st of the month that also provides an answer to your question regarding scheduling an event on the 1st of every month. The routine is to run (in the background) every day until it reaches this particular occurrence.

How does Laravels task scheduling work without persisting the last completed date?

Laravel is (correctly) running scheduled tasks via the App\Console\Kernel#schedule method. It does this without the need for a persistance layer. Previously ran scheduled tasks aren't saved to the database or stored in anyway.
How is this "magic" achieved? I want to have a deeper understanding.
I have looked through the source, and I can see it is somewhat achieved by rounding down the current date and diffing that to the schedule frequency, along with the fact that it is required to run every minute, it can say with a certain level of confidence that it should run a task. That is my interpretation, but I still can't fully grasp how it is guaranteeing to run on schedule and how it handles failure or things being off by a few seconds.
EDIT Edit due to clarity issue pointed out in comment.
By "a few seconds" I mean how does the "round down" method work, even when it is ran every minute, but not at the same second - example: first run 00:01.00, 00:01:02, 00:02:04
Maybe to clarify further, and to assist in understanding how it works, is there any boundary guarantees on how it functions? If ran multiple times per minute will it execute per minute tasks multiple times in the minute?
Cronjob can not guarantee seconds precisely. That is why generally no cronjob interval is less than a minute. So, in reality, it doesn't handle "things being off by a few seconds."
What happens in laravel is this, after running scheduling command for the first time the server asks "Is there a queued job?" every minute. If none, it doesn't do anything.
For example, take the "daily" cronjob. Scheduler doesn't need to know when was the last time it ran the task or something like this. When it encounters the daily cronjob it simply checks if it is midnight. If it is midnight it runs the job.
Also, take "every thirty minute" cronjob. Maybe you registered the cronjob at 10:25. But still the first time it will run on 10:30, not on 10:55. It doesn't care what time you registered or when was the last time it ran. It only checks if the current minute is "00" or divisible by thirty. So at 10:30 it will run. Again, it will run on 11:00. and so on.
Similarly a ten minute cronjob by default will only check if the current minute is divisible by ten or not. So, regardless of the time you registered the command it will run only on XX:00, XX:10, XX:20 and so on.
That is why by default it doesn't need to store previously ran scheduled task. However, you can store it into a file if you want for monitoring purpose.

Generating cron configuration with bash?

In my problem, I will be given a number n. I need to create a cron configuration to run a script as once in n day.
For example if n=20, script should run once per 20 day.
Any advice?
That configuration is going to be dead ugly, if not impossible to do (you possible have to enumerate each day it will be ever executed..)
It's a lot easier to create a configuration so it's executed every day. Then within the script (or in a wrapper script) check that it should actually be executed.
This check can be done with
arithmetic, something like: daycounter=$(( ($(date +%s) / (60*60*24) ) % 20))
with a state file, which has the creation date that stores the last execution time
The file based solution is more fault-tolerant, if your server is down on the day of the schedule, it's going to execute it the next day, while the arithmetic is scheduled on the next cycle (20 days later).
If you wrap the functionality in a file, your cron entry will look very nice:
10 1 * * * executeeveryxday nameofthestatefile 20 "command to execute"
Of course if you have more servers and entries, and want to manage this from a central place, perhaps it's better to fetch the tasks from a database..

How to run a per second cron job every two minutes

I have to set up a cron job on my hosting provider.
This cron job needs to run every second. It's not intensive, just doing a check.
The hosting provider however only allows cron jobs to be run every two minutes. (can't change hosting btw)
So, I'm clueless on how to go about this?
My thoughts so far:
If it can only run every two minutes, I need to make it run every second for two minutes. 1) How do I make my script run for two minutes executing a function every second?
But it's important that there are no interruptions. 2) I have to ensure that it runs smoothly and that it remains constantly active.
Maybe I can also try making it run forever, and run the cron job every two minutes checking whether it is running? 3) Is this possible?
My friend mentioned using multithreading to ensure it's running every second. 4) any comments on this?
Thanks for any advice. I'm using ZF.
Approach #3 is the standard solution. For instance you can have the cron job touch a file every time it runs. Then on startup you can check whether that file has been touched recently, and if it has then exit immediately. Else start running. (Other approaches include using file locking, or else writing the pid to a file and on startup check whether that pid exists and is the expected program.)
As for the one second timeout, I would suggest calling usleep at the end of your query, supplying the number of milliseconds from now to when you next want to run. If you do a regular sleep then you'll actually run less than once a second because sleeps sometimes last longer than expected, and your check takes time. As long as your check takes under a second to run, this should work fine.
I don't think cron allows second level resolution. http://unixhelp.ed.ac.uk/CGI/man-cgi?crontab+5
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)
So, even if your hosting provider allows you can't run a process that repeats every second. However, you can user command something like watch for repeated execution of your script. see here

Resources