Running a cronjob with Laravel 5.6 (using the Sche

2019-07-29 17:11发布

问题:

In my application, I have a few tasks that should run automatically at set intervals. So my immediate thought was: I could make a cron job on the server.

I have got myself started by reading a few articles:

  • Setting up cronjobs in Laravel - https://scotch.io/@Kidalikevin/how-to-set-up-cron-job-in-laravel
  • The difference between normal cronjobs and the Laravel way - https://code.tutsplus.com/tutorials/tasks-scheduling-in-laravel--cms-29815
  • This article on what path\to\artisan actually means - https://laracasts.com/discuss/channels/laravel/pathtoartisan-where-it-is

As well as the Laravel documentation on scheduling.

I'm attempting to have Facebook and Twitter posts pull into a database from an API.

Updating Facebook and Twitter

<?php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

use App\Article;
use App\TwitterPost;
use App\FacebookPost;
use Twitter;

class UpdateSocial extends Command
{
  /**
   * The name and signature of the console command.
   *
   * @var string
   */
  protected $signature = 'update:social';

  /**
   * The console command description.
   *
   * @var string
   */
  protected $description = 'Updates facebook and twitter feeds to DB';

  /**
   * Create a new command instance.
   *
   * @return void
   */
  public function __construct()
  {
    parent::__construct();
  }

  public function updateFacebook()
  {

      //Access token
      $access_token = 'secret';
      //Request the public posts.
      $json_str = file_get_contents('https://graph.facebook.com/v3.0/NewableGroup/feed?access_token='.$access_token);
      //Decode json string into array
      $facebookData = json_decode($json_str);

      //For each facebook post
      foreach($facebookData->data as $data){

          //Convert provided date to appropriate date format
          $fbDate = date("Y-m-d H:i:s", strtotime($data->created_time));
          $fbDateToStr = strtotime($fbDate);

          //If a post contains any text
          if(isset($data->message)){

            //Create new facebook post if it does not already exist in the DB
            $facebookPost = FacebookPost::firstOrCreate(
                  ['post_id' => $data->id], ['created_at' => $fbDateToStr, 'content' => $data->message, 'featuredImage' => null]
            );

            //Output any new facebook posts to the console.
            if($facebookPost->wasRecentlyCreated){
                $this->info("New Facebook Post Added --- " . $facebookPost->content);
             }

          }

      }

  }

  public function updateTwitter($amount)
  {

      $twitterData = Twitter::getUserTimeline(['count' => $amount, 'tweet_mode'=>'extended', 'format' => 'array']);

      foreach($twitterData as $data){

          //Convert provided date to appropriate date format
          $tweetDate = date("Y-m-d H:i:s", strtotime($data['created_at']));
          $tweetDateToStr = strtotime($tweetDate);
          $tweetImg = null;

          //Get the twitter image if any
          if(!empty($data['extended_entities']['media']))
          {
              foreach($data['extended_entities']['media'] as $v){
                  $tweetImg = $v['media_url'];
              }
          }

          //Create new tweet if it does not already exist in the DB
          $twitterPost = TwitterPost::firstOrCreate(
              ['post_id' => $data['id']], ['created_at' => $tweetDateToStr, 'content' => $data['full_text'], 'featuredImage' => $tweetImg]
          );

          //Output any new twitter posts to the console.
          if($twitterPost->wasRecentlyCreated){
             $this->info("New Tweet Added --- " . $twitterPost->content);
          }

      }

  }

  /**
   * Execute the console command.
   *
   * @return mixed
   */
  public function handle()
  {
    $this->updateFacebook();
    $this->updateTwitter(20);
  }
}

This is a console command within Laravel, which is registered in Kernal.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\UpdateSocial'
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('update:social')->everyTenMinutes();
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}

Which enables me to run the command: php artisan update:social, but, evidently for this to happen automatically I need to set up a cron job on the server.

The documentation repeats this line in a few places:

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

I know that * * * * * is the equivalent of every minute of every day and schedule:run is pretty self-explanatory but what is the last part?

This part specifically:

>> /dev/null 2>&1

Also, why must it run every minute on the server even though it'll only run every 10 minutes anyway?

Also, can you use the same setup to run these jobs on a local server like xxamp?

Update

Another user provided a greate link: https://unix.stackexchange.com/questions/163352/what-does-dev-null-21-mean-in-this-article-of-crontab-basics

This explains the final part of the cronjob command nicely.

Picture for reference:

回答1:

You're using xamp, so I assume you're on windows. I suggest you download and install https://sourceforge.net/projects/cronw/ Then you can use unix style cronjobs to run your jobs.

You can also look into using the windows task scheduler, but using the cron scheduler works better in my opinion because the windows task scheduler only allows once per 5 minute triggers.

You'll also need to follow the instructions in the INSTALL file to get cronw up and running. But once it runs it's very easy to manage just like unix crontab's

You run the Laravel scheduler every minute, but the Laravel scheduler then looks into what needs to be run in it's schedule.

You have Cron triggering your scheduler.
Then your scheduler loads it's jobs.
It iterates those and filters out that are not scheduled yet
Eglible scheduled jobs are executed.

Cron is just a way to kick the scheduler to see if there are any pending jobs eglible to be run.

If you just wish to run artisan commands and not use the scheduler service you don't need to run every minute, but you can let the cron job run every 10 minutes.

Personally i'd advice a scheduler job to be run, since you can then have it not execute if the previous process hasn't finished yet, stopping two processes executing simultaneously.

The >> /dev/null 2>&1 is as posted in the link https://unix.stackexchange.com/questions/163352/what-does-dev-null-21-mean-in-this-article-of-crontab-basics as a comment by rkj a simple way to prevent an automatic email to be sent to you as a status report.