• Wprowadzenie
  • Definiowanie harmonogramów
    • Rozkazy Artisan
    • Rozkazy kolejkowania zadań
    • Rozkazy Shell
    • Opcje częstotliwości harmonogramów
    • Strefy czasowe
    • Zapobieganie nakładaniu się zadań
    • .

    • Running Tasks On One Server
    • Background Tasks
    • Maintenance Mode
  • Running The Scheduler
    • Running The Scheduler Locally
  • Task Output
  • Task Hooks

Wprowadzenie

W przeszłości, mogłeś napisać wpis w konfiguracji crona dla każdego zadania, które chciałeś zaplanować na swoim serwerze. Jednakże, może to szybko stać się uciążliwe, ponieważ harmonogram zadań nie jest już w kontroli źródłowej i musisz SSH do swojego serwera, aby zobaczyć istniejące wpisy cron lub dodać dodatkowe wpisy.

Laravel’s command scheduler oferuje świeże podejście do zarządzania zaplanowanymi zadaniami na Twoim serwerze. Harmonogram pozwala na płynne i ekspresyjne definiowanie harmonogramu poleceń w samej aplikacji Laravel. Kiedy używasz harmonogramu, tylko jeden wpis crona jest potrzebny na twoim serwerze. Twój harmonogram zadań jest zdefiniowany w metodzie app/Console/Kernel.php pliku schedule. Aby pomóc Ci zacząć, prosty przykład jest zdefiniowany wewnątrz tej metody.

Definiowanie harmonogramów

Możesz zdefiniować wszystkie swoje zaplanowane zadania w metodzie schedule klasy App\Console\Kernel Twojej aplikacji. Aby zacząć, przyjrzyjmy się przykładowi. W tym przykładzie, zaplanujemy zamknięcie, które będzie wywoływane każdego dnia o północy. W ramach zamknięcia wykonamy zapytanie do bazy danych, aby wyczyścić 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(); }}

Oprócz planowania przy użyciu zamknięć, możesz również zaplanować obiekty inwokowalne. Obiekty wywołujące są prostymi klasami PHP, które zawierają metodę __invoke:

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

Jeśli chcesz zobaczyć przegląd zaplanowanych zadań i następny czas, kiedy mają zostać uruchomione, możesz użyć polecenia schedule:list Artisan:

php artisan schedule:list

Scheduling Artisan Commands

W dodatku do planowania zamknięć, możesz również zaplanować polecenia Artisan i polecenia systemowe. Na przykład możesz użyć metody command do zaplanowania polecenia Artisan przy użyciu nazwy lub klasy polecenia.

Przy planowaniu poleceń Artisan przy użyciu nazwy klasy polecenia możesz przekazać tablicę dodatkowych argumentów wiersza poleceń, które powinny być dostarczone do polecenia, gdy jest ono wywoływane:

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

Zaplanuj zadania w kolejce

Metoda job może być użyta do zaplanowania zadania w kolejce. Ta metoda zapewnia wygodny sposób planowania zadań w kolejce bez używania metody call do definiowania zamknięć w celu umieszczenia zadania w kolejce:

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

Do metody job można przekazać opcjonalny drugi i trzeci argument, który określa nazwę kolejki i połączenie kolejki, które powinny być używane do umieszczenia zadania w kolejce:

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

Metody exec można użyć do wydania polecenia systemowi operacyjnemu:

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

Schedule Frequency Options

Zobaczyliśmy już kilka przykładów tego, jak można skonfigurować zadanie do uruchamiania w określonych odstępach czasu. Istnieje jednak o wiele więcej częstotliwości harmonogramu zadań, które można przypisać do zadania:

.

.

.

Metoda Opis
->cron('* * * * *'); Uruchom zadanie w niestandardowym harmonogramie cron
->everyMinute(); Uruchamiaj zadanie co minutę
->everyTwoMinutes(); Uruchamiaj zadanie co dwie minuty
->everyThreeMinutes(); Rozpoczynaj zadanie co trzy minuty
->everyFourMinutes(); Rozpoczywaj zadanie co cztery minuty
->everyFiveMinutes(); Rozpoczywaj zadanie co pięć minut
->everyTenMinutes(); Rozpocznij zadanie co dziesięć minut
->everyFifteenMinutes(); Rozpocznij zadanie co piętnaście minut
->everyThirtyMinutes(); Rozpocznij zadanie co trzydzieści minut
->hourly(); Rozpocznij zadanie co godzinę
->hourlyAt(17); Uruchamiaj zadanie co godzinę o 17 minut po godzinie
->everyTwoHours(); Uruchamiaj zadanie co dwie godziny
->everyThreeHours(); Rozpoczynaj zadanie co trzy godziny
->everyFourHours(); Rozpoczywaj zadanie co cztery godziny
->everySixHours(); Rozpoczywaj zadanie co sześć godzin
->daily(); Uruchamiaj zadanie codziennie o północy
->dailyAt('13:00'); Uruchamiaj zadanie codziennie o 13:00
->twiceDaily(1, 13); Uruchom zadanie codziennie o 1:00 & 13:00
->weekly(); Uruchom zadanie w każdą niedzielę o 00:00
->weeklyOn(1, '8:00'); Uruchamiaj zadanie co tydzień w poniedziałek o godzinie 8:00
->monthly(); Uruchamiaj zadanie pierwszego dnia każdego miesiąca o godzinie 00:00
->monthlyOn(4, '15:00'); Uruchamiaj zadanie co miesiąc 4 dnia każdego miesiąca o godzinie 15:00
->twiceMonthly(1, 16, '13:00'); Uruchamiaj zadanie co miesiąc 1 i 16 dnia każdego miesiąca o godzinie 13:00
->lastDayOfMonth('15:00'); Uruchomienie zadania w ostatnim dniu miesiąca o godz. 15:00
->quarterly(); Uruchomienie zadania w pierwszym dniu każdego kwartału o godzinie 00:00
->yearly(); Uruchom zadanie pierwszego dnia każdego roku o godzinie 00:00
->yearlyOn(6, 1, '17:00'); Uruchom zadanie każdego roku 1 czerwca o godzinie 17:00
->timezone('America/New_York'); Ustaw strefę czasową dla zadania

Metody te można łączyć z dodatkowymi ograniczeniami, aby tworzyć jeszcze bardziej precyzyjne harmonogramy, które uruchamiają się tylko w określone dni tygodnia. Na przykład, można zaplanować polecenie do uruchamiania co tydzień w poniedziałek:

// 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');

Listę dodatkowych ograniczeń harmonogramu można znaleźć poniżej:

.

.

Metoda Opis
->weekdays(); Zawężenie zadania do dni tygodnia
->weekends(); Zawężenie zadania do weekendów
->sundays(); Zawężenie zadania do niedziel
->mondays(); Zawęzić zadanie do poniedziałku
->tuesdays(); Zawęzić zadanie do wtorku
->wednesdays(); Zawęzić zadanie do środy
->thursdays(); Ograniczyć zadanie do czwartku
->fridays(); Ograniczyć zadanie do piątku
Ograniczyć zadanie do piątku
->saturdays(); Zawęzić zadanie do soboty
->days(array|mixed); Zawęzić zadanie do określonych dni
Zawęzić zadanie do określonych dni
->between($startTime, $endTime); Zawężenie zadania do uruchamiania między czasem rozpoczęcia i zakończenia
->unlessBetween($startTime, $endTime); Zawężenie zadania do nie uruchamiania między czasem rozpoczęcia i końcem
->when(Closure); Ograniczyć zadanie na podstawie testu prawdy
->environments($env); Ograniczyć zadanie do określonych środowisk

Day Constraints

Metoda days może być użyta do ograniczenia wykonywania zadania do określonych dni tygodnia. Na przykład można zaplanować, aby polecenie było uruchamiane co godzinę w niedziele i środy:

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

Alternatywnie można użyć stałych dostępnych w klasie Illuminate\Console\Scheduling\Schedule podczas określania dni, w których zadanie powinno być uruchamiane:

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

Between Time Constraints

Metody between można użyć do ograniczenia wykonywania zadania na podstawie pory dnia:

$schedule->command('emails:send') ->hourly() ->between('7:00', '22:00');

Podobnie, metoda unlessBetween może być użyta do wykluczenia wykonania zadania przez pewien okres czasu:

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

Truth Test Constraints

Metoda when może być użyta do ograniczenia wykonania zadania na podstawie wyniku danego testu prawdy. Innymi słowy, jeśli dane zamknięcie zwróci true, zadanie zostanie wykonane tak długo, jak długo żadne inne warunki ograniczające nie uniemożliwią uruchomienia zadania:

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

Metodę skip można postrzegać jako odwrotność when. Jeśli metoda skip zwróci true, zaplanowane zadanie nie zostanie wykonane:

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

Przy użyciu łańcuchowych metod when zaplanowane polecenie zostanie wykonane tylko wtedy, gdy wszystkie warunki when zwrócą true.

Ograniczenia środowiska

Metoda environments może być używana do wykonywania zadań tylko na podanych środowiskach (określonych przez zmienną środowiskową APP_ENV):

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

Timezones

Używając metody timezone, możesz określić, że czas zaplanowanego zadania powinien być interpretowany w ramach danej strefy czasowej:

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

Jeśli wielokrotnie przypisujesz tę samą strefę czasową do wszystkich swoich zaplanowanych zadań, możesz chcieć zdefiniować metodę scheduleTimezone w swojej klasie App\Console\Kernel. Metoda ta powinna zwrócić domyślną strefę czasową, która powinna być przypisana do wszystkich zaplanowanych zadań:

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

{note} Pamiętaj, że niektóre strefy czasowe wykorzystują czas letni. W przypadku zmiany czasu letniego zaplanowane zadanie może zostać uruchomione dwukrotnie lub nie zostać uruchomione w ogóle. Z tego powodu zalecamy unikanie planowania według strefy czasowej, jeśli to możliwe.

Zapobieganie nakładaniu się zadań

Domyślnie zaplanowane zadania są uruchamiane, nawet jeśli poprzednia instancja zadania jest nadal uruchomiona. Aby temu zapobiec, można użyć metody withoutOverlapping:

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

W tym przykładzie polecenie emails:send Artisan będzie uruchamiane co minutę, jeśli nie jest już uruchomione. Metoda withoutOverlapping jest szczególnie przydatna, jeśli masz zadania, których czas wykonania drastycznie się różni, uniemożliwiając dokładne przewidzenie, ile czasu zajmie dane zadanie.

W razie potrzeby możesz określić, ile minut musi upłynąć, zanim wygaśnie blokada „bez nakładania się”. Domyślnie, blokada wygaśnie po 24 godzinach:

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

Running Tasks On One Server

{note} Aby korzystać z tej funkcji, Twoja aplikacja musi używać sterownika pamięci podręcznej database, memcached, dynamodb lub redis jako domyślnego sterownika pamięci podręcznej Twojej aplikacji. Ponadto wszystkie serwery muszą komunikować się z tym samym centralnym serwerem pamięci podręcznej.

Jeśli harmonogram Twojej aplikacji działa na wielu serwerach, możesz ograniczyć zaplanowane zadanie do wykonywania tylko na jednym serwerze. Na przykład, załóżmy, że masz zaplanowane zadanie, które generuje nowy raport w każdy piątek wieczorem. Jeśli harmonogram zadań działa na trzech serwerach, zaplanowane zadanie zostanie uruchomione na wszystkich trzech serwerach i wygeneruje raport trzy razy. Niedobrze!

Aby wskazać, że zadanie powinno być uruchamiane tylko na jednym serwerze, należy użyć metody onOneServer podczas definiowania zaplanowanego zadania. Pierwszy serwer, który otrzyma zadanie, zabezpieczy blokadę atomową zadania, aby uniemożliwić innym serwerom uruchomienie tego samego zadania w tym samym czasie:

$schedule->command('report:generate') ->fridays() ->at('17:00') ->onOneServer();

Zadania w tle

Domyślnie wiele zadań zaplanowanych w tym samym czasie będzie wykonywanych sekwencyjnie na podstawie kolejności, w jakiej zostały zdefiniowane w metodzie schedule. Jeśli masz długo działające zadania, może to spowodować, że kolejne zadania zaczną się znacznie później niż przewidywano. Jeśli chcesz uruchamiać zadania w tle, aby wszystkie były wykonywane jednocześnie, możesz użyć metody runInBackground:

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

{note} Metoda runInBackground może być użyta tylko podczas planowania zadań za pomocą metod command i exec.

Tryb konserwacji

Zaplanowane zadania Twojej aplikacji nie będą uruchamiane, gdy aplikacja jest w trybie konserwacji, ponieważ nie chcemy, aby Twoje zadania kolidowały z niedokończoną konserwacją, którą możesz wykonywać na swoim serwerze. Jeśli jednak chcesz zmusić zadanie do uruchomienia nawet w trybie konserwacji, możesz wywołać metodę evenInMaintenanceMode podczas definiowania zadania:

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

Running The Scheduler

Teraz, gdy dowiedzieliśmy się, jak definiować zaplanowane zadania, omówmy, jak faktycznie uruchomić je na naszym serwerze. Polecenie schedule:run Artisan oceni wszystkie zaplanowane zadania i określi, czy muszą zostać uruchomione w oparciu o aktualny czas serwera.

Więc, kiedy używamy harmonogramu Laravela, musimy tylko dodać pojedynczy wpis konfiguracji crona do naszego serwera, który uruchamia polecenie schedule:run co minutę. Jeśli nie wiesz jak dodać wpisy cron do swojego serwera, rozważ użycie usługi takiej jak Laravel Forge, która może zarządzać wpisami cron dla Ciebie:

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

Running The Scheduler Locally

Typowo, nie dodasz wpisu cron schedulera do swojej lokalnej maszyny deweloperskiej. Zamiast tego, możesz użyć polecenia schedule:work Artisan. To polecenie będzie działać na pierwszym planie i wywoływać scheduler co minutę, dopóki go nie zakończysz:

php artisan schedule:work

Wyjście zadania

Scheduler Laravela zapewnia kilka wygodnych metod pracy z wyjściem generowanym przez zaplanowane zadania. Po pierwsze, używając metody sendOutputTo, możesz wysłać dane wyjściowe do pliku w celu późniejszego sprawdzenia:

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

Jeśli chcesz dołączyć dane wyjściowe do danego pliku, możesz użyć metody appendOutputTo:

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

Używając metody emailOutputTo, możesz wysłać dane wyjściowe pocztą elektroniczną na wybrany adres e-mail. Przed wysłaniem pocztą elektroniczną danych wyjściowych z zadania należy skonfigurować usługi poczty elektronicznej Laravela:

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

Jeśli chcesz wysłać pocztą elektroniczną dane wyjściowe tylko wtedy, gdy zaplanowane polecenie Artisana lub systemowe zakończy się niezerowym kodem wyjścia, użyj metody emailOutputOnFailure:

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

{note} Metody emailOutputTo, emailOutputOnFailure, sendOutputTo i appendOutputTo są wyłączne w stosunku do metod command i exec.

Haki zadań

Używając metod before i after, można określić kod, który zostanie wykonany przed i po wykonaniu zaplanowanego zadania:

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

Metody onSuccess i onFailure pozwalają określić kod, który zostanie wykonany, jeśli zaplanowane zadanie powiedzie się lub nie powiedzie. Niepowodzenie wskazuje, że zaplanowane polecenie Artisan lub systemowe zakończyło się niezerowym kodem wyjścia:

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

Jeśli dane wyjściowe są dostępne z twojego polecenia, możesz uzyskać do nich dostęp w swoich hakach after, onSuccess lub onFailure przez wskazanie instancji Illuminate\Support\Stringable jako argumentu $output definicji zamknięcia twojego haka:

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

Pingowanie adresów URL

Używając metod pingBefore i thenPing, harmonogram może automatycznie pingować dany adres URL przed lub po wykonaniu zadania. Ta metoda jest przydatna do powiadamiania usługi zewnętrznej, takiej jak Envoyer, o rozpoczęciu lub zakończeniu wykonywania zaplanowanego zadania:

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

Metody pingBeforeIf i thenPingIf mogą być używane do pingowania danego adresu URL tylko wtedy, gdy dany warunek jest true:

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

Metody pingOnSuccess i pingOnFailure mogą być używane do pingowania danego adresu URL tylko wtedy, gdy zadanie powiedzie się lub nie powiedzie. Niepowodzenie oznacza, że zaplanowane polecenie Artisana lub systemowe zakończyło się z niezerowym kodem wyjścia:

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

Wszystkie metody ping wymagają biblioteki HTTP Guzzle. Guzzle jest domyślnie instalowany we wszystkich nowych projektach Laravel, ale możesz ręcznie zainstalować Guzzle w swoim projekcie za pomocą menedżera pakietów Composer, jeśli został on przypadkowo usunięty:

composer require guzzlehttp/guzzle