- 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
- Definiowanie harmonogramów
- Scheduling Artisan Commands
- Zaplanuj zadania w kolejce
- Scheduling Shell Commands
- Schedule Frequency Options
- Day Constraints
- Between Time Constraints
- Truth Test Constraints
- Ograniczenia środowiska
- Timezones
- Zapobieganie nakładaniu się zadań
- Running Tasks On One Server
- Zadania w tle
- Tryb konserwacji
- Running The Scheduler
- Running The Scheduler Locally
- Wyjście zadania
- Haki zadań
- Pingowanie adresów URL
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
lubredis
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ą metodcommand
iexec
.
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
iappendOutputTo
są wyłączne w stosunku do metodcommand
iexec
.
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
Dodaj komentarz