2016-10-20 2 views
8

Umwelt


Beschreibung

Ich versuche, alle 1 Minute einen Befehl mit Laravel Task Scheduling auszuführen.


Versuch

ich diese Zeile in meine cron Registerkarte Datei hinzugefügt haben

* * * * * php artisan schedule:run >> /dev/null 2>&1

Hier ist meine /app/Console/Kernel.php

<?php 

namespace App\Console; 

use Illuminate\Console\Scheduling\Schedule; 
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; 

class Kernel extends ConsoleKernel 
{ 
    /** 
    * The Artisan commands provided by your application. 
    * 
    * @var array 
    */ 
    protected $commands = [ 
     \App\Console\Commands\Inspire::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('echo "Happy New Year!" ')->everyMinute(); //<---- ADD HERE  } 
} 

Ich habe diese Zeilehinzugefügt


Frage

Wie dies getestet werden?

Wie trigge ich mein Echo zur Anzeige?

Woher weiß ich, ob das, was ich getan habe, nicht falsch ist?


Ich bin offen für alle Vorschläge in diesem Moment.

Alle Hinweise/Vorschläge/hilft auf diesem werden sehr geschätzt!

+1

Was ich gemacht habe ist, dass jeder "Befehl" tatsächlich ein ausführbarer Handwerkerbefehl ist. Dann können Sie diesen Befehl selbst testen, um sicherzustellen, dass er das tut, was Sie wollen. Ich prüfe nicht, dass der Scheduler wie erwartet funktioniert, weil er vom Framework bereitgestellt wird, so dass ich davon ausgehen kann, dass er funktioniert. Das Einzige, was verwundbar bleibt, ist, wenn Sie einen Tippfehler gemacht haben oder den Scheduler falsch eingerichtet haben, aber wenn Sie den Dokumenten folgen, gibt es keinen Grund, warum es nicht funktionieren sollte und es würde einfach nur testen, ob jemand Ihnen gesagt hat, dass Sie alles außer dem Wert testen sollen ist minimal .. fühlen Sie sich frei zu widersprechen – tam5

Antwort

6

command() führt einen Handwerkerbefehl aus. Was Sie versuchen zu erreichen - einen Befehl an die OS Ausgabe - von exec('echo "Happy New Year!"')

Testing getan wird, hängt davon ab, was Sie testen wollen:

  • Ob der Scheduler (jede Minute) arbeitet?

In diesem Fall müssen Sie nicht. Es wird im ursprünglichen Framework-Code getestet.

  • Ob der Befehl erfolgreich ist?

Nun können Sie manuell php artisan schedule:run ausführen und die Ausgabe sehen.

Der Scheduler produziert keine Ausgabe auf Standard (>> /dev/null 2>&1). Sie können jedoch die Ausgabe der ausgeführten Skripts in eine beliebige Datei umleiten, indem Sie writeOutputTo() oder appendOutputTo()() verketten.


Für komplexere Logik, schreiben einen Konsolenbefehl statt (https://laravel.com/docs/5.1/artisan#writing-commands) und verwenden command() - diese Weise können Sie schöne, prüfbare Code schreiben können.

+0

Ich habe meine Linie '$ Schedule-> Befehl aktualisieren ('curl http://wttr.in/01851')-() alleMinute() -> sendOutputTo(public_path().'/ tasks/log.txt '); 'und bekomme mein Log zum export, aber in meiner log.txt öffne ich es, ich sehe' [InvalidArgumentException] Command "curl" ist nicht definiert. "Was habe ich möglicherweise falsch gemacht? – ihue

+0

@ihue Die Befehlsfunktion führt Handwerkerbefehle, nicht Terminalbefehle zum Betriebssystem – tam5

+0

Wie ich oben schrieb, benutze '$ schedule-> exec()' anstelle von 'command()' :) – nXu

2

Wenn Sie die Terminplanung von Ereignissen testen möchten, können Sie dieses Beispiel verwenden. Es basiert auf dem Standard inspirieren Befehl:

public function testIsAvailableInTheScheduler() 
{ 
    /** @var \Illuminate\Console\Scheduling\Schedule $schedule */ 
    $schedule = app()->make(\Illuminate\Console\Scheduling\Schedule::class); 

    $events = collect($schedule->events())->filter(function (\Illuminate\Console\Scheduling\Event $event) { 
     return stripos($event->command, 'YourCommandHere'); 
    }); 

    if ($events->count() == 0) { 
     $this->fail('No events found'); 
    } 

    $events->each(function (\Illuminate\Console\Scheduling\Event $event) { 
     // This example is for hourly commands. 
     $this->assertEquals('0 * * * * *', $event->expression); 
    }); 
} 
0

Aufbauend auf Michiel Antwort, habe ich die Methoden in Illuminate\Console\Scheduling\Event enthalten ist, verwendet, um zu testen, ob das Ereignis fällig ist für ein bestimmtes Datum laufen.

Ich habe das aktuelle Datum mit Carbon::setTestNow() verspottet, so dass jede Datum basierte Logik in den when() und skip() Filter wie erwartet verhalten wird.

use Tests\TestCase; 
use Illuminate\Console\Scheduling\Schedule; 
use Illuminate\Console\Scheduling\Event; 

use Cron\CronExpression; 
use Carbon\Carbon; 


class ScheduleTest extends TestCase { 


    public function testCompanyFeedbackSchedule() 
    { 
     $event = $this->getCommandEvent('your-command-signature'); 

     $test_date = Carbon::now()->startOfDay()->addHours(8); 

     for ($i=0; $i < 356; $i++) { 
      $test_date->addDay(); 
      Carbon::setTestNow($test_date); 

      // Run the when() & skip() filters 
      $filters_pass = $event->filtersPass($this->app); 
      // Test that the Cron expression passes 
      $date_passes = $this->isEventDue($event); 
      $will_run = $filters_pass && $date_passes; 

      // Should only run on first friday of month 
      if ($test_date->format('l') === 'Friday' && $test_date->weekOfMonth === 1) { 
       $this->assertTrue($will_run, 'Task should run on '. $test_date->toDateTimeString()); 
      } else { 
       $this->assertFalse($will_run, 'Task should not run on '. $test_date->toDateTimeString()); 
      } 
     } 
    } 


    /** 
    * Get the event matching the given command signature from the scheduler 
    * 
    * @param string $command_signature 
    * 
    * @return Illuminate\Console\Scheduling\Event 
    */ 
    private function getCommandEvent($command_signature) 
    { 
     $schedule = app()->make(Schedule::class); 

     $event = collect($schedule->events())->first(function (Event $event) use ($command_signature) { 
      return stripos($event->command, $command_signature); 
     }); 

     if (!$event) { 
      $this->fail('Event for '. $command_signature .' not found'); 
     } 

     return $event; 
    } 


    /** 
    * Determine if the Cron expression passes. 
    * 
    * Copied from the protected method Illuminate\Console\Scheduling\[email protected] 
    * 
    * @return bool 
    */ 
    private function isEventDue(Event $event) 
    { 
     $date = Carbon::now(); 

     if ($event->timezone) { 
      $date->setTimezone($event->timezone); 
     } 

     return CronExpression::factory($event->expression)->isDue($date->toDateTimeString()); 
    } 
}