首页 > 解决方案 > 使用 Laravel 5.6 运行 cronjob(使用调度程序)

问题描述

在我的应用程序中,我有一些任务应该以设定的时间间隔自动运行。所以我的直接想法是:我可以在服务器上做一个 cron 作业。

我已经开始阅读一些文章:

以及关于调度的 Laravel 文档。

我正在尝试将 Facebook 和 Twitter 帖子从 API 提取到数据库中。

更新脸书和推特

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

这是 Laravel 中的一个控制台命令,注册在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');
    }
}

这使我能够运行命令:php artisan update:social,但是,显然要自动发生这种情况,我需要在服务器上设置一个 cron 作业。

文档在几个地方重复了这一行:

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

我知道这* * * * *相当于每天的每一分钟,而且schedule:run不言自明,但最后一部分是什么?

这部分具体:

>> /dev/null 2>&1

另外,为什么它必须在服务器上每分钟运行一次,即使它只会每 10 分钟运行一次?

此外,您可以使用相同的设置在本地服务器上运行这些作业xxamp吗?

更新

另一位用户提供了一个很棒的链接:https ://unix.stackexchange.com/questions/163352/what-does-dev-null-21-mean-in-this-article-of-crontab-basics

这很好地解释了 cronjob 命令的最后一部分。

图片供参考:

在此处输入图像描述

标签: phplaravellaravel-5

解决方案


您正在使用 xamp,所以我假设您在 Windows 上。我建议您下载并安装https://sourceforge.net/projects/cronw/ 然后您可以使用 unix 样式的 cronjobs 来运行您的作业。

您也可以考虑使用 windows 任务调度程序,但我认为使用 cron 调度程序效果更好,因为 windows 任务调度程序只允许每 5 分钟触发一次。

您还需要按照安装文件中的说明来启动和运行 cronw。但是一旦它运行它就像 unix crontab 一样很容易管理

您每分钟运行一次Laravel 调度程序,但 Laravel 调度程序随后会查看需要在其调度中运行的内容。

你有 Cron 触发你的调度程序。
然后你的调度程序加载它的工作。
它会迭代那些并过滤掉那些尚未计划但
已执行 Egible 计划的作业。

Cron 只是一种启动调度程序以查看是否有任何待处理的作业可以运行的方法。

如果您只想运行 artisan 命令而不使用调度程序服务,则不需要每分钟运行一次,但您可以让 cron 作业每 10 分钟运行一次。

我个人建议运行一个调度程序作业,因为如果前一个进程尚未完成,您可以让它不执行,停止同时执行的两个进程。

>> /dev/null 2>&1链接https://unix.stackexchange.com/questions/163352/what-does-dev-null-21-mean-in-this-article-of-crontab-basics作为rkj a的评论发布防止将自动电子邮件作为状态报告发送给您的简单方法。


推荐阅读