Laravel - 调用 Artisan 命令并等待结果

Laravel - call Artisan command and wait for the result

我试图在控制器中调用一个非常耗时的 Artisan 命令(它在 20-90 秒内执行),但我有两个问题。首先,似乎命令根本没有执行(如果我 return 输出它只是 returns "0")。

其次,另一部分(returning the file)不等待命令执行(但它可以与第一部分相关)。这是我的代码:

public function returnZip()
{
    // just a failsafe, in case if scheduled command did not created the file yet
    if( ! file_exists( storage_path( '/app/exports/' . date('Y_m_d') . '.zip' ) ) ){
        Artisan::call('maximus:export');
    }

    return response()->file( storage_path( '/app/exports/' . date('Y_m_d') . '.zip' ) );
}

如何从 route/controller 正确执行 Artisan 命令并等待它完成任务?

编辑

我尝试进一步调试这个问题,发现从 route/controller 调用时根本没有执行该命令。

试过这个:

Route::get('/test', function(){
    Artisan::call('maximus:export');
    return ['ok'];
});

我的命令应该创建一个文件:

public function handle()
{
    exec('touch /some/path/storage/app/exports/test');
 }

当我 运行 在终端中执行此命令时,正在创建文件,但是当我点击路由时,却没有。有任何想法吗?

我很确定 artisan 命令是异步处理的,所以它不会等待命令完成。因此,您的回复很可能是 empty/malformed.

您可能需要查看 EventsListeners 以确保您的操作顺序正确 (https://laravel.com/docs/5.4/events)。

例如,在您的 maximus:export 命令中,您可以在文件创建后立即触发一个事件。

示例:

创建一个名为 ZipCreated 的事件和一个名为 SendZip 的侦听器。然后在您的 artisan 命令处理程序中调用事件:

event(new ZipCreated($file));

然后link它给你EventServiceProvider.php中的一个听众:

protected $listen = [
    Events\Repository\ZipCreated::class => [
        Listeners\Repository\SendZip::class,
    ],
];

这样 ZipCreated 将为 SendZip 提供压缩文件(或文件路径,如果需要)并且 SendZip 可以处理将文件返回给用户。

现在只要命令是 运行,文件的创建和响应的处理将始终以正确的顺序发生。

if I return the output it just returns "0"

让我指出,以防万一 call 方法不是 return 命令的输出,而是它的退出代码(“0”表示成功)。相反,Artisan::output() 将 return 输出。

我会说检查日志看看发生了什么,还要检查你实际上 useing Artisan facade。否则,尝试调试器或插入信息性 dd() 语句 ;)(入口点是 Illuminate\Foundation\Console\Kernel::call)。

好的,我启动了 Laravel 并进行了测试。我的命令是:

public function handle()
{
    exec('touch ' . storage_path(str_random(16) . '.txt'));
}

通过调用 Artisan::call().

,它在终端和路由中都能完美运行

大胆猜测:www-data 用户(或您的网络服务器使用的 PHP 是 运行 的任何用户)是否有足够的权限来写入文件?

试试这个: dd(Artisan::输出());