• Indledning
  • Definition af tidsplaner
    • Skemalægning af Artisan-kommandoer
    • Skemalægning af opgaver i kø
    • Skemalægning af Shell-kommandoer
    • Optioner for planlægningsfrekvens
    • Tidszoner
    • Forebyggelse af overlapning af opgaver
    • Kørsel af opgaver på én server
    • Baggrundsopgaver
    • Maintenance Mode
  • Kørsel af Scheduleren
    • Kørsel af Scheduleren lokalt
  • Task Output
  • Task Hooks

Indledning

I fortiden, har du måske skrevet en cron-konfigurationspost for hver opgave, du havde brug for at planlægge på din server. Dette kan dog hurtigt blive en plage, fordi din opgaveplanlægning ikke længere er i kildekontrollen, og du skal SSH ind på din server for at få vist dine eksisterende cron-poster eller tilføje yderligere poster.

Laravels kommandoskemalægger tilbyder en ny tilgang til administration af planlagte opgaver på din server. Scheduleren giver dig mulighed for flydende og udtryksfuldt at definere din kommandoskema inden for selve din Laravel-applikation. Når du bruger scheduleren, er der kun brug for en enkelt cron-post på din server. Din opgaveskema er defineret i app/Console/Kernel.php-filens schedule-metode. For at hjælpe dig i gang er der defineret et simpelt eksempel i metoden.

Definering af tidsplaner

Du kan definere alle dine planlagte opgaver i schedule-metoden i din applikations App\Console\Kernel-klasse App\Console\Kernel. Lad os se på et eksempel for at komme i gang. I dette eksempel vil vi planlægge en lukning, der skal kaldes hver dag ved midnat. Inden for lukningen vil vi udføre en databaseforespørgsel for at rydde en tabel:

<?phpnamespace App\Console;use Illuminate\Console\Scheduling\Schedule;use Illuminate\Foundation\Console\Kernel as ConsoleKernel;use Illuminate\Support\Facades\DB;class Kernel extends ConsoleKernel{ /** * The Artisan commands provided by your application. * * @var array */ protected $commands = ; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->call(function () { DB::table('recent_users')->delete(); })->daily(); }}

Ud over at planlægge ved hjælp af lukninger kan du også planlægge invokable objekter. Invokable objekter er simple PHP-klasser, der indeholder en __invoke metode:

$schedule->call(new DeleteRecentUsers)->daily();

Hvis du gerne vil have vist en oversigt over dine planlagte opgaver og den næste gang, de skal køre, kan du bruge kommandoen schedule:list Artisan:

php artisan schedule:list

Scheduling Artisan Commands

Ud over at planlægge lukninger kan du også planlægge Artisan kommandoer og systemkommandoer. Du kan f.eks. bruge metoden command til at planlægge en Artisan-kommando ved hjælp af enten kommandoens navn eller klasse.

Når du planlægger Artisan-kommandoer ved hjælp af kommandoklassens navn, kan du sende et array af yderligere kommandolinjeargumenter, der skal gives til kommandoen, når den påkaldes:

use App\Console\Commands\SendEmailsCommand;$schedule->command('emails:send Taylor --force')->daily();$schedule->command(SendEmailsCommand::class, )->daily();

Planlægning af job i kø

Metoden job kan bruges til at planlægge et job i kø. Denne metode giver en bekvem måde at planlægge job i kø på uden at bruge call-metoden til at definere lukninger til at sætte jobbet i kø:

use App\Jobs\Heartbeat;$schedule->job(new Heartbeat)->everyFiveMinutes();

Det er muligt at angive andet og tredje argument til job-metoden, som angiver det kønavn og den køforbindelse, der skal bruges til at sætte jobbet i kø:

use App\Jobs\Heartbeat;// Dispatch the job to the "heartbeats" queue on the "sqs" connection...$schedule->job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();

Scheduling Shell Commands

Metoden exec kan bruges til at sende en kommando til operativsystemet:

$schedule->exec('node /home/forge/script.js')->daily();

Schedule Frequency Options

Vi har allerede set et par eksempler på, hvordan du kan konfigurere en opgave til at køre med bestemte intervaller. Der er dog mange flere opgaveplanfrekvenser, som du kan tildele en opgave:

Metode Beskrivelse
->cron('* * * * *'); Kør opgaven på en brugerdefineret cron-plan
->everyMinute(); Kør opgaven hvert minut
->everyTwoMinutes(); Kør opgaven hvert andet minut
->everyThreeMinutes(); Kør opgaven hvert tredje minut
->everyFourMinutes(); Kør opgaven hvert fjerde minut
->everyFiveMinutes(); Kør opgaven hvert femte minut
->everyTenMinutes(); Kør opgaven hvert tiende minut
->everyFifteenMinutes(); Kør opgaven hvert femtende minut
->everyThirtyMinutes(); Kør opgaven hvert tredive minut
->hourly(); Kør opgaven hver time
->hourlyAt(17); Kør opgaven hver time kl. 17 minutter over kl.
->everyTwoHours(); Kør opgaven hver anden time
->everyThreeHours(); Kør opgaven hver tredje time
->everyFourHours(); Kør opgaven hver fjerde time
->everySixHours(); Kør opgaven hver sjette time
->daily(); Kør opgaven hver dag kl. 24.00
->dailyAt('13:00'); Kør opgaven hver dag kl. 13:00
->twiceDaily(1, 13); Kør opgaven dagligt kl. 1:00 & 13:00
->weekly(); Kør opgaven hver søndag kl. 00:00
->weeklyOn(1, '8:00'); Kør opgaven hver uge mandag kl. 8:00
->monthly(); Kør opgaven den første dag i hver måned kl. 00:00
->monthlyOn(4, '15:00'); Kør opgaven hver måned den 4. kl. 15:00
->twiceMonthly(1, 16, '13:00'); Kør opgaven hver måned den 1. og den 16. kl. 13:00
->lastDayOfMonth('15:00'); Kør opgaven den sidste dag i måneden kl. 15:00
->quarterly(); Kør opgaven på den første dag i hvert kvartal kl:00
->yearly(); Kør opgaven på den første dag i hvert år kl. 00:00
->yearlyOn(6, 1, '17:00'); Kør opgaven hvert år den 1. juni kl. 17:00
->timezone('America/New_York'); Sæt tidszonen for opgaven

Disse metoder kan kombineres med yderligere begrænsninger for at oprette endnu mere finjusterede skemaer, der kun kører på bestemte ugedage. Du kan f.eks. planlægge en kommando til at køre ugentligt om mandagen:

// Run once per week on Monday at 1 PM...$schedule->call(function () { //})->weekly()->mondays()->at('13:00');// Run hourly from 8 AM to 5 PM on weekdays...$schedule->command('foo') ->weekdays() ->hourly() ->timezone('America/Chicago') ->between('8:00', '17:00');

Der findes en liste over yderligere planlægningsbegrænsninger nedenfor:

til onsdag

Metode Beskrivelse
->weekdays(); Begræns opgaven til ugedage
->weekends(); Begrænse opgaven til weekender
->sundays(); Begrænse opgaven til søndag
->mondays(); Begræns opgaven til mandag
->tuesdays(); Begræns opgaven til tirsdag
->wednesdays(); Begræns opgaven til tirsdag
->tuesdays();
->thursdays(); Begrænse opgaven til torsdag
->fridays(); Begrænse opgaven til fredag
->saturdays(); Begrænse opgaven til lørdag
->days(array|mixed); Begrænse opgaven til bestemte dage
->between($startTime, $endTime); Begrænse opgaven til at køre mellem start- og sluttidspunkter
->unlessBetween($startTime, $endTime); Begrænse opgaven til ikke at køre mellem start- og sluttidspunkter
->when(Closure); Begræns opgaven på baggrund af en sandhedstest
->environments($env); Begræns opgaven til bestemte miljøer

Day Constraints

Metoden days kan bruges til at begrænse udførelsen af en opgave til bestemte dage i ugen. Du kan f.eks. planlægge en kommando til at køre hver time om søndagen og onsdagen:

$schedule->command('emails:send') ->hourly() ->days();

Alternativt kan du bruge de konstanter, der er tilgængelige i Illuminate\Console\Scheduling\Schedule-klassen, når du definerer de dage, en opgave skal køre:

use Illuminate\Console\Scheduling\Schedule;$schedule->command('emails:send') ->hourly() ->days();

Between Time Constraints

Metoden between kan bruges til at begrænse udførelsen af en opgave på grundlag af tidspunktet på dagen:

Sådan kan unlessBetween-metoden anvendes til at udelukke udførelsen af en opgave i en bestemt periode:

$schedule->command('emails:send') ->hourly() ->unlessBetween('23:00', '4:00');

Sandhedstestbegrænsninger

Metoden when kan anvendes til at begrænse udførelsen af en opgave på grundlag af resultatet af en given sandhedstest. Med andre ord, hvis den givne lukning returnerer true, vil opgaven blive udført, så længe ingen andre begrænsende betingelser forhindrer opgaven i at blive udført:

$schedule->command('emails:send')->daily()->when(function () { return true;});

Metoden skip kan ses som det omvendte af when. Hvis skip-metoden returnerer true, vil den planlagte opgave ikke blive udført:

$schedule->command('emails:send')->daily()->skip(function () { return true;});

Ved brug af kædeordnede when-metoder vil den planlagte opgave kun blive udført, hvis alle when-betingelser returnerer true.

Miljøbegrænsninger

Metoden environments kan bruges til kun at udføre opgaver på de givne miljøer (som defineret af miljøvariablen APP_ENV):

$schedule->command('emails:send') ->daily() ->environments();

Timezones

Med metoden timezone kan du angive, at en planlagt opgaves tid skal fortolkes inden for en given tidszone:

$schedule->command('report:generate') ->timezone('America/New_York') ->at('2:00')

Hvis du gentagne gange tildeler den samme tidszone til alle dine planlagte opgaver, kan du definere en scheduleTimezone-metode i din App\Console\Kernel-klasse. Denne metode skal returnere den standardtidszone, der skal tildeles alle planlagte opgaver:

/** * Get the timezone that should be used by default for scheduled events. * * @return \DateTimeZone|string|null */protected function scheduleTimezone(){ return 'America/Chicago';}

{note} Husk, at nogle tidszoner anvender sommertid. Når sommertiden ændres, kan det være, at din planlagte opgave kører to gange eller måske slet ikke kører. Derfor anbefaler vi, at du så vidt muligt undgår planlægning i tidszoner.

Forebyggelse af opgaveoverlapninger

Som standard køres planlagte opgaver, selv om den tidligere instans af opgaven stadig kører. Hvis du vil forhindre dette, kan du bruge metoden withoutOverlapping:

$schedule->command('emails:send')->withoutOverlapping();

I dette eksempel vil emails:send Artisan-kommandoen blive kørt hvert minut, hvis den ikke allerede kører. withoutOverlapping-metoden er især nyttig, hvis du har opgaver, der varierer drastisk i deres udførelsestid, hvilket forhindrer dig i at forudsige præcis, hvor lang tid en given opgave vil tage.

Hvis det er nødvendigt, kan du angive, hvor mange minutter der skal gå, før låsen “uden overlapning” udløber. Som standard udløber låsen efter 24 timer:

$schedule->command('emails:send')->withoutOverlapping(10);

Kørsel af opgaver på én server

{note} For at udnytte denne funktion skal dit program bruge database, memcached, dynamodb eller redis cachedriveren som dit programs standardcacheledriver. Desuden skal alle servere kommunikere med den samme centrale cacheserver.

Hvis dit programs scheduler kører på flere servere, kan du begrænse et planlagt job til kun at blive udført på en enkelt server. Antag f.eks., at du har en planlagt opgave, der genererer en ny rapport hver fredag aften. Hvis opgaveplanlæggeren kører på tre arbejdsservere, vil den planlagte opgave blive kørt på alle tre servere og generere rapporten tre gange. Det er ikke godt!

For at angive, at opgaven kun skal køre på én server, skal du bruge metoden onOneServer, når du definerer den planlagte opgave. Den første server, der får opgaven, vil sikre en atomisk lås på opgaven for at forhindre andre servere i at køre den samme opgave på samme tid:

Baggrundsopgaver

Som standard vil flere opgaver, der er planlagt på samme tid, blive udført i rækkefølge baseret på den rækkefølge, de er defineret i din schedule-metode. Hvis du har opgaver, der kører længe, kan dette medføre, at efterfølgende opgaver starter meget senere end forventet. Hvis du ønsker at køre opgaver i baggrunden, så de alle kan køre samtidigt, kan du bruge runInBackground-metoden:

$schedule->command('analytics:report') ->daily() ->runInBackground();

{note} runInBackground-metoden må kun bruges, når du planlægger opgaver via command– og exec-metoderne.

Vedligeholdelsestilstand

Din programs planlagte opgaver kører ikke, når programmet er i vedligeholdelsestilstand, da vi ikke ønsker, at dine opgaver skal forstyrre eventuel ufærdig vedligeholdelse, du måtte være i gang med på din server. Hvis du imidlertid ønsker at tvinge en opgave til at køre selv i vedligeholdelsestilstand, kan du kalde metoden evenInMaintenanceMode, når du definerer opgaven:

$schedule->command('emails:send')->evenInMaintenanceMode();

Kørsel af Scheduler

Nu da vi har lært, hvordan du definerer planlagte opgaver, skal vi diskutere, hvordan du rent faktisk kører dem på vores server. Kommandoen schedule:run Artisan vil evaluere alle dine planlagte opgaver og bestemme, om de skal køres baseret på serverens aktuelle tid.

Så når vi bruger Laravels scheduler, behøver vi kun at tilføje en enkelt cron-konfigurationspost til vores server, der kører kommandoen schedule:run hvert minut. Hvis du ikke ved, hvordan du tilføjer cron-poster til din server, kan du overveje at bruge en tjeneste som Laravel Forge, der kan administrere cron-posterne for dig:

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Kørsel af scheduleren lokalt

Typisk ville du ikke tilføje en scheduler-cron-post til din lokale udviklingsmaskine. I stedet kan du bruge kommandoen schedule:work Artisan. Denne kommando kører i forgrunden og påkalder scheduleren hvert minut, indtil du afslutter kommandoen:

php artisan schedule:work

Task Output

Laravel scheduler giver flere praktiske metoder til at arbejde med det output, der genereres af planlagte opgaver. For det første kan du ved hjælp af sendOutputTo-metoden sende output til en fil til senere kontrol:

$schedule->command('emails:send') ->daily() ->sendOutputTo($filePath);

Hvis du ønsker at vedhæfte output til en given fil, kan du bruge appendOutputTo-metoden:

$schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);

Med emailOutputTo-metoden kan du sende output til en e-mailadresse efter eget valg. Før du sender output af en opgave pr. e-mail, skal du konfigurere Laravels e-mailtjenester:

$schedule->command('report:generate') ->daily() ->sendOutputTo($filePath) ->emailOutputTo('');

Hvis du kun ønsker at sende output pr. e-mail, hvis den planlagte Artisan eller systemkommando afsluttes med en exitkode på ikke-nul, skal du bruge emailOutputOnFailure-metoden:

$schedule->command('report:generate') ->daily() ->emailOutputOnFailure('');

{note} Metoderne emailOutputTo, emailOutputOnFailure, sendOutputTo og appendOutputTo er eksklusive i forhold til metoderne command og exec.

Task Hooks

Med metoderne before og after kan du angive kode, der skal udføres før og efter, at den planlagte opgave udføres:

$schedule->command('emails:send') ->daily() ->before(function () { // The task is about to execute... }) ->after(function () { // The task has executed... });

Med metoderne onSuccess og onFailure kan du angive kode, der skal udføres, hvis den planlagte opgave lykkes eller mislykkes. En fiasko angiver, at den planlagte Artisan- eller systemkommando blev afsluttet med en exitkode, der ikke er nul:

$schedule->command('emails:send') ->daily() ->onSuccess(function () { // The task succeeded... }) ->onFailure(function () { // The task failed... });

Hvis output er tilgængeligt fra din kommando, kan du få adgang til det i dine after, onSuccess eller onFailure hooks ved at typehintge en Illuminate\Support\Stringable-instans som $output-argumentet i din hooks lukningsdefinition:

use Illuminate\Support\Stringable;$schedule->command('emails:send') ->daily() ->onSuccess(function (Stringable $output) { // The task succeeded... }) ->onFailure(function (Stringable $output) { // The task failed... });

Ping af URL’er

Med pingBefore– og thenPing-metoderne kan scheduleren automatisk pinge en given URL før eller efter, at en opgave er blevet udført. Denne metode er nyttig til at underrette en ekstern tjeneste, f.eks. Envoyer, om, at din planlagte opgave er ved at begynde eller er færdig med at blive udført:

$schedule->command('emails:send') ->daily() ->pingBefore($url) ->thenPing($url);

Metoderne pingBeforeIf og thenPingIf kan bruges til kun at pinge en given URL, hvis en given betingelse er true:

$schedule->command('emails:send') ->daily() ->pingBeforeIf($condition, $url) ->thenPingIf($condition, $url);

Metoderne pingOnSuccess og pingOnFailure kan bruges til kun at pinge en given URL, hvis opgaven lykkes eller mislykkes. En fiasko angiver, at den planlagte Artisan- eller systemkommando blev afsluttet med en exitkode, der ikke er nul:

$schedule->command('emails:send') ->daily() ->pingOnSuccess($successUrl) ->pingOnFailure($failureUrl);

Alle ping-metoderne kræver Guzzle HTTP-biblioteket. Guzzle installeres typisk som standard i alle nye Laravel-projekter, men du kan manuelt installere Guzzle i dit projekt ved hjælp af Composer-pakkehåndteringsprogrammet, hvis det ved et uheld er blevet fjernet:

composer require guzzlehttp/guzzle