Generating cron configuration with bash? - algorithm

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..

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.

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.

Crontab on week numbers

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.

Cronjob every two weeks

I want to run a cronjob every two weeks on Sundays at midnight.
This is what I've tried.
0 0 * * 0/2 /path/to/script
Is this correct?
Will it execute the next Sunday and then every two weeks? I cant test it on my server at this point.. Please help.
Thanks.
AFAIK cron can't handle "every second week".
Instead, you could run it every Sunday at midnight and modify the script exit early if it's not one of the Sundays you want it to run.
If modification of the script is not possible, create a wrapper script that only calls the main script when it's a scheduled Sunday and call the wrapper from cron.

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