I do heavy automation on servers.
Biggest problem is the time-based execution of automation things.
The idea is to use a cron-syntax-style to time the executions.
So I need a way to check if a command that is combined to a cron syntax string can be executed now.
Things like:
./parser.sh 0 0 * * *
will only return OK on Midnight not on all the other minutes of a day.
Also
./parser.sh */10 0,1,2,3,4-22/4 * * *
and all combinations possible in cron syntax needs to work.
There will be several executions per day, every execution has different syntax.
Is there any kind of stuff that can do this?
It is not possible to actually create cronjobs for this.
Only can use Bash, maybe static compiled binaries, no Python nor higher languages.
Already tried https://github.com/morganhk/BashCronParse but this cannot interpret things like 1,2,3,4,5... only single numbers and */n, neither combinations.
I cannot get your question clearly. But, if you are trying to run parser.sh every minute of the day.
Use this
./parser.sh * * * * *
Related
I am looking to fire off a task everyday at 9am. I am getting some funky results. Currently my job looks like this:
#Scheduled(cron = "0 0 9 * * ?")
What is going wrong with this? Is this the correct expression?
I believe #Scheduled(cron="0 0 9 * * *") should work. Also make sure that you are on right time zone. Have a look at this video to know different possible ways to use cron expression with #Scheduled.
In Laravel, in my Kernel, I have:
protected $commands = [
Commands\SendRenewEmails::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
$schedule->command('renew:emails')
->daily();
}
The said function renew:emails, works as intended if I run this manually trough Artisan.
And in my crontab I have:
* */8 * * * cd /path-to-my-project && php artisan schedule:run >> /dev/null 2>&1
I have this to run every 8th hour, instead of every minute at * * * * *, since this is live for testing, and just to ensure that the task wasnt run every minute.
So how does Laravel know, when to run the daily job on the kernal, and when does this happen?
From this setup (which seems to be the basic setup for cronjobs in Laravel, but to run every minute instead of every 8th hour), there is no logs (that I can see), and no table in DB to keep track of this.
So if I where to set my cron to * * * * *, how does Laravel know not to run the scheduled job every minute, just because I have put ->daily(); at the end of the job?
And when I have daily();, at what specific time is that? And at specific what time is hourly();?
TL;DR:
How does Laravel know not to run the same jobs again if it is not supposed to, for example with daily(); rule? Where is this information stored? How can I be certain that a job with rule daily(); wont run every minute if my cronjobs std:out's php artisan schedule:run every minute?
Under the hood, the Laravel Scheduler uses https://github.com/dragonmantank/cron-expression to determine if a command or job is scheduled to run at the given minute the schedule:run is called.
Each task you schedule translates to a cron expression, which is then passed into the package. A method called isDue is then run against that expression to determine whether or not it should run. So, if you set a task to run hourly, then isDue will yield true at the top of the hour, and Laravel will execute to the task within the cron cycle.
As such, the information does not need to be stored anywhere, as determination is done on the fly.
This might also lead you to wonder what might happen if you have a long-running task that might take longer than the interval. This is where withoutOverlapping comes into the picture. When called, it creates what is known as a mutex, which is similar to a 'lock' of sorts (see What is a mutex? for more information), when the task is initially run. If a mutex already exists for a particular task on subsquent cycles, it means that task is currently running in another cycle, and should not be triggered again in this one.
Where are mutexes stored? Simple: Laravel stores them in a cache, and when a mutexed task is finished, the mutex is removed from the cache. And so the cycle continues.
I could go into much further detail here, but I think this answers your question for the most part.
rufus-scheduler lib allows us to schedule tasks
https://github.com/jmettraux/rufus-scheduler
require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new
scheduler.cron '* * * * *' do
# do something every minute
end
In fact, when you want to test your app on top of rufus-scheduler you will need to sleep real 1 min which is too much for typical tests.
For example, in Reactor(Java) they provide StepVerifier.withVirtualTime in order to avoid long-running tests.`:
https://projectreactor.io/docs/core/release/reference/#_manipulating_time
https://www.baeldung.com/reactive-streams-step-verifier-test-publisher#3-testing-time-based-publishers
RxJava - https://medium.com/#vanniktech/taking-control-of-the-time-when-testing-rxjava-code-91b2e5e88bdf
Are there any options for time manipulation within tests for rufus-scheduler or Ruby itself?
Current solution
rufus-scheduler has type in, thus for verification of app skeleton I'm using in=0.001s and sleep 0.4.
Yes, it takes half-of a second in the test but this is much better than 1 minute.
Have a look at
https://github.com/travisjeffery/timecop
https://andycroll.com/ruby/replace-timecop-with-rails-time-helpers-in-rspec/
or other "time travel" tools.
I second #spickermann on "only test your own code".
I'm trying to run a cron on start-up and then midnight every day from that point.
I'm bound by Dashing to use Rufus Scheduler 2.0.24, in which I can't use 'first_in' with the cron command. The command in 3.x I want to replicate is like so...
scheduler.cron '00 00 * * *', :first_in => '0' do
I'm wondering if there is any way around this?
I found this which describes a similar issue - but this will only run the cron at the first instance of the specified allotted time and not immediately.
a plain way of doing it would be:
job =
proc do
puts "hello"
end
job.call
# run it right now
scheduler.cron('00 00 * * *', &job)
But maybe this one is more readable:
job =
scheduler.cron '00 00 * * *' do
puts 'hello'
end
job.block.call
# run it right now
scheduler.join
Thanks for posting a new question, it made everything clear. The question at Rufus Scheduler :first_in option unknown with cron is a bit different.
I know this is about rufus-scheduler 2.0.24, but I'd like to point to a new feature in 3.3.x: https://github.com/jmettraux/rufus-scheduler/issues/214 where you can do job.trigger_off_schedule and it invokes the job right now if overlap, mutex and other job options allow it.
Back to 2.0.24, the shortcut shown above has no refinement, it will run the block right now. The block might already have an instance running now, imagine you have the schedule set for "midnight every night" and you happen to restart at midnight. Hence, I think the first solution above, is best, because it triggers then schedules.
I would like to schedule a cron job at 5am and 1830
I tried
0,30 5,18 * * *
but this actually run four times a day at
0500
0530
1800
1830
Can I set up cron to do this? I am using spring to run this cron job so if I cant do it using standard cron can I do it another way?
Thanks
You need to schedule it with two lines:
0 5 * * *
30 18 * * *
There is no way to specify some minutes/hours combination: if you define two couples of them, all combinations will be performed.