• Einführung
  • Definieren von Zeitplänen
    • Planen von Artisan-Befehlen
    • Planen von Jobs in der Warteschlange
    • Planen von Shell-Befehlen
    • Optionen für die Planungshäufigkeit
    • Zeitzonen
    • Verhindern von Task-Überlappungen
    • Ausführen von Tasks auf einem Server
    • Hintergrundtasks
    • Wartungsmodus
  • Ausführen des Schedulers
    • Lokales Ausführen des Schedulers
  • Task-Ausgabe
  • Task-Hooks

Einführung

In der Vergangenheit, haben Sie vielleicht einen Cron-Konfigurationseintrag für jede Aufgabe geschrieben, die Sie auf Ihrem Server planen wollten. Dies kann jedoch schnell lästig werden, da Ihr Aufgabenplan nicht mehr in der Quellcode-Kontrolle ist und Sie sich per SSH in Ihren Server einloggen müssen, um Ihre bestehenden Cron-Einträge zu sehen oder zusätzliche Einträge hinzuzufügen.

Laravels Befehlsplaner bietet einen neuen Ansatz für die Verwaltung von geplanten Aufgaben auf Ihrem Server. Der Scheduler ermöglicht es Ihnen, Ihren Befehlszeitplan fließend und ausdrucksstark innerhalb Ihrer Laravel-Anwendung selbst zu definieren. Wenn Sie den Scheduler verwenden, ist nur ein einziger Cron-Eintrag auf Ihrem Server erforderlich. Ihr Aufgabenplan wird in der app/Console/Kernel.php-Datei in der schedule-Methode definiert. Um Ihnen den Einstieg zu erleichtern, ist in der Methode ein einfaches Beispiel definiert.

Definieren von Zeitplänen

Sie können alle Ihre geplanten Aufgaben in der Methode schedule der Klasse App\Console\Kernel Ihrer Anwendung definieren. Schauen wir uns zum Einstieg ein Beispiel an. In diesem Beispiel planen wir einen Abschluss, der jeden Tag um Mitternacht aufgerufen wird. Innerhalb der Schließung führen wir eine Datenbankabfrage aus, um eine Tabelle zu löschen:

<?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(); }}

Neben der Zeitplanung mit Schließungen können Sie auch aufrufbare Objekte planen. Aufrufbare Objekte sind einfache PHP-Klassen, die eine __invoke-Methode enthalten:

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

Wenn Sie sich einen Überblick über Ihre geplanten Aufgaben und deren nächste Ausführung verschaffen möchten, können Sie den schedule:list-Artisan-Befehl verwenden:

php artisan schedule:list

Artisan-Befehle planen

Neben der Planung von Abschlüssen können Sie auch Artisan-Befehle und Systembefehle planen. Sie können zum Beispiel die Methode command verwenden, um einen Artisan-Befehl entweder über den Namen oder die Klasse des Befehls zu planen.

Wenn Sie Artisan-Befehle über den Klassennamen des Befehls planen, können Sie ein Array zusätzlicher Befehlszeilenargumente übergeben, die dem Befehl beim Aufrufen übergeben werden sollen:

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

Scheduling Queued Jobs

Die Methode job kann verwendet werden, um einen Job in der Warteschlange zu planen. Diese Methode bietet eine bequeme Möglichkeit, Jobs in der Warteschlange zu planen, ohne die Methode call zu verwenden, um Abschlüsse zu definieren, um den Job in die Warteschlange zu stellen:

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

Optional können der Methode job ein zweites und ein drittes Argument übergeben werden, die den Namen der Warteschlange und die Verbindung zur Warteschlange angeben, die für die Warteschlange des Jobs verwendet werden soll:

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

Shell-Befehle einplanen

Mit der Methode exec kann ein Befehl an das Betriebssystem gesendet werden:

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

Optionen für die Einplanungshäufigkeit

Wir haben bereits einige Beispiele dafür gesehen, wie Sie eine Aufgabe so konfigurieren können, dass sie in bestimmten Abständen ausgeführt wird. Es gibt jedoch noch viele weitere Optionen, die Sie einer Aufgabe zuweisen können:

Methode Beschreibung
->cron('* * * * *'); Ausführen der Aufgabe nach einem benutzerdefinierten Cron-Plan
->everyMinute(); Die Aufgabe jede Minute ausführen
->everyTwoMinutes(); Die Aufgabe alle zwei Minuten ausführen
->everyThreeMinutes(); Ausführen der Aufgabe alle drei Minuten
->everyFourMinutes(); Ausführen der Aufgabe alle vier Minuten
->everyFiveMinutes(); Ausführen der Aufgabe alle fünf Minuten
->everyTenMinutes(); Ausführen der Aufgabe alle zehn Minuten
->everyFifteenMinutes(); Ausführen der Aufgabe alle fünfzehn Minuten
->everyThirtyMinutes(); Ausführen der Aufgabe alle dreißig Minuten
->hourly(); Ausführen der Aufgabe jede Stunde
->hourlyAt(17); Die Aufgabe jede Stunde um 17 Minuten nach der vollen Stunde ausführen
->everyTwoHours(); Die Aufgabe alle zwei Stunden ausführen
->everyThreeHours(); Ausführen der Aufgabe alle drei Stunden
->everyFourHours(); Ausführen der Aufgabe alle vier Stunden
->everySixHours(); Ausführen der Aufgabe alle sechs Stunden
->daily(); Ausführen der Aufgabe jeden Tag um Mitternacht
->dailyAt('13:00'); Ausführen der Aufgabe jeden Tag um 13:00
->twiceDaily(1, 13); Ausführen der Aufgabe täglich um 1:00 & 13:00
->weekly(); Ausführen der Aufgabe jeden Sonntag um 00:00
->weeklyOn(1, '8:00'); Ausführen der Aufgabe jede Woche am Montag um 8:00
->monthly(); Ausführen der Aufgabe am ersten Tag eines jeden Monats um 00:00
->monthlyOn(4, '15:00'); Ausführen der Aufgabe jeden Monat am 4. um 15:00
->twiceMonthly(1, 16, '13:00'); Ausführen der Aufgabe monatlich am 1. und 16. um 13:00
->lastDayOfMonth('15:00'); Ausführen der Aufgabe am letzten Tag des Monats um 15:00
->quarterly(); Ausführen der Aufgabe am ersten Tag jedes Quartals um 00:00
->yearly(); Ausführen der Aufgabe am ersten Tag eines jeden Jahres um 00:00
->yearlyOn(6, 1, '17:00'); Ausführen der Aufgabe jedes Jahr am 1. Juni um 17:00
->timezone('America/New_York'); Setzen Sie die Zeitzone für die Aufgabe

Diese Methoden können mit zusätzlichen Einschränkungen kombiniert werden, um noch feiner abgestimmte Zeitpläne zu erstellen, die nur an bestimmten Wochentagen ausgeführt werden. Sie können zum Beispiel einen Befehl so planen, dass er wöchentlich am Montag ausgeführt wird:

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

Eine Liste zusätzlicher Zeitplanbeschränkungen finden Sie unten:

Methode Beschreibung
->weekdays(); Beschränkung der Aufgabe auf Wochentage
->weekends(); Beschränke die Aufgabe auf Wochenenden
->sundays(); Beschränke die Aufgabe auf Sonntag
->mondays(); Beschränke die Aufgabe auf Montag
->tuesdays(); Beschränke die Aufgabe auf Dienstag
->wednesdays(); Beschränke die Aufgabe auf Mittwoch
->thursdays(); Beschränke die Aufgabe auf Donnerstag
->fridays(); Beschränke die Aufgabe auf Freitag
->saturdays(); Beschränke die Aufgabe auf Samstag
->days(array|mixed); Beschränke die Aufgabe auf bestimmte Tage
->between($startTime, $endTime); Einschränken, dass die Aufgabe zwischen Start- und Endzeit läuft
->unlessBetween($startTime, $endTime); Einschränken, dass die Aufgabe zwischen Start- und Endzeit nicht läuft Endzeiten
->when(Closure); Beschränken Sie die Aufgabe basierend auf einem Wahrheitstest
->environments($env); Beschränken Sie die Aufgabe auf bestimmte Umgebungen

Tageinschränkungen

Die Methode days kann verwendet werden, um die Ausführung einer Aufgabe auf bestimmte Wochentage zu beschränken. Sie können beispielsweise einen Befehl so planen, dass er sonntags und mittwochs stündlich ausgeführt wird:

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

Alternativ können Sie die Konstanten der Klasse Illuminate\Console\Scheduling\Schedule verwenden, um die Tage zu definieren, an denen eine Aufgabe ausgeführt werden soll:

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

Zwischenzeitbeschränkungen

Die Methode between kann verwendet werden, um die Ausführung einer Aufgabe auf der Grundlage der Tageszeit zu beschränken:

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

Ahnlich kann die Methode unlessBetween verwendet werden, um die Ausführung einer Aufgabe für einen bestimmten Zeitraum auszuschließen:

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

Wahrheitstest-Beschränkungen

Die Methode when kann verwendet werden, um die Ausführung einer Aufgabe auf der Grundlage des Ergebnisses eines gegebenen Wahrheitstests zu beschränken. Mit anderen Worten, wenn die gegebene Schließung true ergibt, wird die Aufgabe ausgeführt, solange keine anderen einschränkenden Bedingungen die Ausführung der Aufgabe verhindern:

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

Die Methode skip kann als Umkehrung von when angesehen werden. Wenn die skip-Methode true zurückgibt, wird die geplante Aufgabe nicht ausgeführt:

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

Bei Verwendung verketteter when-Methoden wird der geplante Befehl nur ausgeführt, wenn alle when-Bedingungen true zurückgeben.

Umgebungseinschränkungen

Die environments-Methode kann verwendet werden, um Aufgaben nur in den angegebenen Umgebungen auszuführen (wie durch die APP_ENV-Umgebungsvariable definiert):

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

Zeitzonen

Mit der Methode timezone können Sie festlegen, dass die Zeit einer geplanten Aufgabe innerhalb einer bestimmten Zeitzone interpretiert werden soll:

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

Wenn Sie allen Ihren geplanten Aufgaben wiederholt dieselbe Zeitzone zuweisen, können Sie eine scheduleTimezone-Methode in Ihrer App\Console\Kernel-Klasse definieren. Diese Methode sollte die Standardzeitzone zurückgeben, die allen geplanten Aufgaben zugewiesen werden sollte:

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

{note} Denken Sie daran, dass einige Zeitzonen die Sommerzeit verwenden. Wenn sich die Sommerzeit ändert, kann es sein, dass Ihre geplante Aufgabe doppelt oder gar nicht ausgeführt wird. Aus diesem Grund empfehlen wir, die Zeitzonenplanung nach Möglichkeit zu vermeiden.

Verhindern von Aufgabenüberschneidungen

Standardmäßig werden geplante Aufgaben auch dann ausgeführt, wenn die vorherige Instanz der Aufgabe noch läuft. Um dies zu verhindern, können Sie die Methode withoutOverlapping verwenden:

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

In diesem Beispiel wird der Befehl emails:send Artisan jede Minute ausgeführt, wenn er nicht bereits läuft. Die withoutOverlapping-Methode ist besonders nützlich, wenn Sie Aufgaben haben, deren Ausführungszeit drastisch variiert, so dass Sie nicht genau vorhersagen können, wie lange eine bestimmte Aufgabe dauern wird.

Bei Bedarf können Sie angeben, wie viele Minuten vergehen müssen, bevor die Sperre „ohne Überschneidung“ abläuft. Standardmäßig läuft die Sperre nach 24 Stunden ab:

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

Aufgaben auf einem Server ausführen

{note} Um diese Funktion nutzen zu können, muss Ihre Anwendung den Cache-Treiber database, memcached, dynamodb oder redis als Standard-Cache-Treiber für Ihre Anwendung verwenden. Außerdem müssen alle Server mit demselben zentralen Cache-Server kommunizieren.

Wenn der Scheduler Ihrer Anwendung auf mehreren Servern ausgeführt wird, können Sie einen geplanten Job auf die Ausführung auf einem einzigen Server beschränken. Nehmen Sie zum Beispiel an, Sie haben eine geplante Aufgabe, die jeden Freitagabend einen neuen Bericht erstellt. Wenn der Aufgabenplaner auf drei Arbeitsservern ausgeführt wird, wird die geplante Aufgabe auf allen drei Servern ausgeführt und der Bericht dreimal erstellt. Nicht gut!

Um anzugeben, dass die Aufgabe nur auf einem Server ausgeführt werden soll, verwenden Sie die Methode onOneServer, wenn Sie die geplante Aufgabe definieren. Der erste Server, der die Aufgabe erhält, sichert eine atomare Sperre für den Auftrag, um zu verhindern, dass andere Server dieselbe Aufgabe zur gleichen Zeit ausführen:

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

Hintergrundaufgaben

Standardmäßig werden mehrere zur gleichen Zeit geplante Aufgaben in der Reihenfolge ausgeführt, in der sie in Ihrer schedule-Methode definiert sind. Wenn Sie lang laufende Aufgaben haben, kann dies dazu führen, dass nachfolgende Aufgaben viel später als erwartet beginnen. Wenn Sie Aufgaben im Hintergrund laufen lassen möchten, so dass sie alle gleichzeitig ausgeführt werden können, können Sie die Methode runInBackground verwenden:

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

{Anmerkung} Die Methode runInBackground kann nur verwendet werden, wenn Aufgaben über die Methoden command und exec geplant werden.

Wartungsmodus

Die geplanten Aufgaben Ihrer Anwendung werden nicht ausgeführt, wenn sich die Anwendung im Wartungsmodus befindet, da wir nicht möchten, dass Ihre Aufgaben mit noch nicht abgeschlossenen Wartungsarbeiten, die Sie auf Ihrem Server durchführen, in Konflikt geraten. Wenn Sie jedoch erzwingen möchten, dass eine Aufgabe auch im Wartungsmodus ausgeführt wird, können Sie bei der Definition der Aufgabe die Methode evenInMaintenanceMode aufrufen:

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

Ausführen des Schedulers

Nachdem wir nun gelernt haben, wie man geplante Aufgaben definiert, wollen wir nun besprechen, wie man sie auf unserem Server ausführt. Der Artisan-Befehl schedule:run wertet alle geplanten Aufgaben aus und bestimmt, ob sie auf der Grundlage der aktuellen Uhrzeit des Servers ausgeführt werden müssen.

Bei Verwendung des Schedulers von Laravel müssen wir also nur einen einzigen Cron-Konfigurationseintrag zu unserem Server hinzufügen, der den Befehl schedule:run jede Minute ausführt. Wenn Sie nicht wissen, wie Sie Ihrem Server Cron-Einträge hinzufügen können, sollten Sie einen Dienst wie Laravel Forge verwenden, der die Cron-Einträge für Sie verwalten kann:

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

Den Scheduler lokal ausführen

Normalerweise würden Sie Ihrem lokalen Entwicklungsrechner keinen Cron-Eintrag für den Scheduler hinzufügen. Stattdessen können Sie den schedule:work Artisan-Befehl verwenden. Dieser Befehl wird im Vordergrund ausgeführt und ruft den Scheduler jede Minute auf, bis Sie den Befehl beenden:

php artisan schedule:work

Task-Ausgabe

Der Laravel-Scheduler bietet mehrere bequeme Methoden für die Arbeit mit der von geplanten Tasks erzeugten Ausgabe. Zunächst können Sie mit der Methode sendOutputTo die Ausgabe in eine Datei zur späteren Überprüfung senden:

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

Wenn Sie die Ausgabe an eine bestimmte Datei anhängen möchten, können Sie die Methode appendOutputTo verwenden:

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

Mit der Methode emailOutputTo können Sie die Ausgabe per E-Mail an eine E-Mail-Adresse Ihrer Wahl senden. Bevor Sie die Ausgabe einer Aufgabe per E-Mail versenden, sollten Sie die E-Mail-Dienste von Laravel konfigurieren:

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

Wenn Sie die Ausgabe nur dann per E-Mail versenden möchten, wenn der geplante Artisan- oder Systembefehl mit einem Exit-Code ungleich Null abbricht, verwenden Sie die Methode emailOutputOnFailure:

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

{note} Die Methoden emailOutputTo, emailOutputOnFailure, sendOutputTo und appendOutputTo sind exklusiv für die Methoden command und exec.

Task Hooks

Mit den Methoden before und after können Sie Code angeben, der vor und nach der Ausführung der geplanten Aufgabe ausgeführt werden soll:

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

Mit den Methoden onSuccess und onFailure können Sie Code angeben, der bei Erfolg oder Misserfolg der geplanten Aufgabe ausgeführt werden soll. Ein Fehlschlag bedeutet, dass der geplante Artisan- oder Systembefehl mit einem Exit-Code ungleich Null beendet wurde:

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

Wenn die Ausgabe Ihres Befehls verfügbar ist, können Sie in Ihren after-, onSuccess– oder onFailure-Hooks darauf zugreifen, indem Sie eine Illuminate\Support\Stringable-Instanz als $output-Argument der Schließungsdefinition Ihres Hooks angeben:

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

Ping URLs

Mit den Methoden pingBefore und thenPing kann der Scheduler automatisch eine bestimmte URL anpingen, bevor oder nachdem eine Aufgabe ausgeführt wird. Diese Methode ist nützlich, um einen externen Dienst, wie z.B. Envoyer, zu benachrichtigen, dass Ihre geplante Aufgabe beginnt oder die Ausführung beendet ist:

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

Die Methoden pingBeforeIf und thenPingIf können verwendet werden, um eine bestimmte URL nur dann anzupingen, wenn eine bestimmte Bedingung erfüllt ist:

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

Die Methoden pingOnSuccess und pingOnFailure können verwendet werden, um eine bestimmte URL nur dann anzupingen, wenn die Aufgabe erfolgreich ist oder fehlschlägt. Ein Fehlschlag bedeutet, dass der geplante Artisan- oder Systembefehl mit einem Exit-Code ungleich Null beendet wurde:

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

Alle Ping-Methoden erfordern die Guzzle-HTTP-Bibliothek. Guzzle wird in der Regel standardmäßig in allen neuen Laravel-Projekten installiert. Sie können Guzzle jedoch auch manuell über den Composer-Paketmanager in Ihr Projekt installieren, wenn es versehentlich entfernt wurde:

composer require guzzlehttp/guzzle