【问题标题】:Laravel - call Artisan command and wait for the resultLaravel - 调用 Artisan 命令并等待结果
【发布时间】:2017-07-07 00:26:42
【问题描述】:

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

其次另一部分(返回文件)不等待命令执行(但可以与第一部分相关)。这是我的代码:

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

如何从路由/控制器正确执行 Artisan 命令并等待它完成任务?

编辑

我尝试再调试一下这个问题,发现从路由/控制器调用该命令时根本没有执行。

试过这个:

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

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

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

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

【问题讨论】:

    标签: laravel laravel-artisan


    【解决方案1】:

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

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

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

    示例:

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

    event(new ZipCreated($file));
    

    然后将其链接到您的EventServiceProvider.php 中的侦听器:

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

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

    现在,无论何时运行命令,文件的创建和响应的处理都将始终以正确的顺序发生。

    【讨论】:

    • 主要问题是从路由/控制器调用时,工匠命令根本没有被执行。在终端一切正常。任何想法如何检查/调试为什么调用不执行命令?
    • 我假设您已经在控制器调用 Artisan 命令之前添加了一个 dd(); 以确保它被访问,因此我会暂时用类似的东西替换您的工匠命令处理程序的内容写入数据库中的表 (DB::table('test')->insert(['test' => 'test']))。这会让我们知道 1) 是否正在执行命令 2) 如果命令的内容是问题所在。如果是后者,那么很可能是权限问题!
    【解决方案2】:

    如果我返回输出,它只会返回“0”

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

    我会说检查日志以了解发生了什么,还要检查您实际上是 useing Artisan 门面。否则,请尝试调试器或插入信息丰富的 dd() 语句;)(入口点是 Illuminate\Foundation\Console\Kernel::call)。

    【讨论】:

      【解决方案3】:

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

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

      通过调用Artisan::call(),它在终端和路由中都能完美运行。

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

      【讨论】:

      • 伙计,就这么简单...我的整个项目有 0777 权限,但我手动创建了 exports 文件夹,它得到了 0755。真可惜。
      • 主要问题是为什么我没有收到错误 - 既没有尝试执行命令,也没有在日志中......
      • 这确实是个好问题,日志中确实应该有错误。我真的不知道为什么没有。
      【解决方案4】:

      试试这个: dd(Artisan::output());

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-18
        • 2016-02-07
        • 1970-01-01
        • 1970-01-01
        • 2017-01-18
        • 2019-05-09
        相关资源
        最近更新 更多