Laravel Google App Engine 上的任务计划

Laravel Task Scheduling on Google App Engine

有什么方法可以在 App Engine 上执行 php artisan 命令吗? 我需要设置 Laravel 的 Task Scheduling,这需要设置以下 cron 作业:

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

但是当我查看 cron.yaml 文档时,没有执行 php 文件的方法,似乎只支持对 URL.[=18= 的 HTTP 调用]

无论如何可以帮我解决这个问题吗?

更新 1 请不要建议从控制器内调用 Artisan::handle($command)。我需要 PHP-CLI 版本的 artisan

我想没有任何建议,我已经通过在网络路由中编写它来做到这一点

Route::get('scheduler', ArtisanController@handle)->middleware('app-engine-cron');

这个在ArtisanController

class ArtisanController extends Controller
{
    public function handle()
    {
        shell_exec('php '.base_path('artisan').' schedule:run > /dev/null 2>/dev/null &');
    }
}

和这个中间件

class AppEngineCronMiddleware
{

    public function handle($request, Closure $next)
    {
        if (!$request->hasHeader('X-Appengine-Cron')) {
            return response()->json(trans('auth.unauthorized'), 401);
        }

        return $next($request);
    }
}

最后cron.yaml像这样

cron:
- description: "Laravel Scheduler"
  url: /scheduler
  schedule: every 1 mins
  target: default

遇到此问题的任何人都可以尝试这个,它按预期对我有用。无论如何,我们非常欢迎其他建议。特别是来自 Google

很抱歉向关注此主题的所有人发出 ping 命令,但我想我会提供另一种解决方案。这可能更像是一个讨论点,非常愿意听取您对此的想法

Artisan 提供了一个 schedule:work 命令:(强调我的)

Typically, you would not add a scheduler cron entry to your local development machine. Instead you may use the schedule:work Artisan command. This command will run in the foreground and invoke the scheduler every minute until you terminate the command

我们目前正在将 GAE 用于一个 Laravel 项目,并且成功地覆盖了 Google App Engine docs 中描述的监督配置。也就是说,在app.yaml中指定runtime_config下的supervisord_conf_override键,它引用了源代码中的库存标准supervisord配置文件。

所以.. 你可以提供一个 supervisord 配置,所以它会监控一个 php artisan schedule:work 命令。例如:

[supervisord]
nodaemon = true
logfile = /dev/null
logfile_maxbytes = 0
pidfile = /var/run/supervisord.pid

[program:laravel-schedule-worker]
command = php %(ENV_APP_DIR)s/artisan schedule:work
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes=0
user = www-data
autostart = true
autorestart = true
priority = 5
stopwaitsecs = 20

[supervisorctl]

这样做的好处当然是不需要达到 shell_exec(...),但是根据我的理解,runtime_config 密钥仅在 GAE 'Flexible' 环境中可用。因此,如果您在 'Standard' 环境中,那么当前接受的答案就是可行的方法。

Laravel 文档将 schedule:work 命令描述为在本地环境中使用的命令,但是我不明白为什么它不能在生产环境中使用...也许有什么我想念的吗?

一个更简单的解决方案是将所有这些放入 1 条路线并使用 Artisan::call() 而不是 shell_exec()

routes/gae.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Route;

Route::get('scheduler', function (Request $request) {
    if(!$request->hasHeader('X-Appengine-Cron')) {
        return abort(401);
    }
    Artisan::call('schedule:run');
    return response('', 204); // no content
});

然后在 app/Providers/RouteServiceProvider.php

中加载此路由文件
    public function boot()
    {
        // ...
        $this->routes(function () {
            // ...

            $this->mapGaeRoutes();
        });
    }

    protected function mapGaeRoutes()
    {
        Route::group(base_path('routes/gae.php'));
    }

或者,只需将那一条路由放入 routes/web.php 并跳过路由提供商修改。

授权

来自 github 用户 stackkit 的这个项目有更好的安全检查,但它只运行作业,不运行计划任务。也许 Artisan::call('schedule:run') 可以找到进入此云任务项目的方法。

您可以通过检查签名和发行者(iss 声明)来了解此项目如何授权 google 提供的 Oidc 令牌。

您可以在不验证签名的情况下简单地检查 google 给出的 Oidc 令牌,如果您可以在服务帐户的自定义声明中隐藏已知的共享秘密,您可以验证并获得少量安全性。

由于这只是运行 artisan schedule,而且每分钟运行,唯一需要防范的就是DoS攻击。

https://github.com/stackkit/laravel-google-cloud-tasks-queue/blob/master/src/TaskHandler.php