没有不值得去解决的问题,也没有不值得去学习的技术!

在 Linux 、Laravel 6 中,任务队列一直运行中的排查分析(已经设置超时时间)

决定在容器中手动执行命令行,执行失败

1、在任务队列中 Artisan::call 了命令,代码如下

PHP

    /**
     * 执行安装主题命令
     * @param string $themeLocation 编译后的主题所在目录
     * @param string $themeId 主题ID
     * @param bool $force 主题ID
     * @return void
     */
    public function installTheme($themeLocation, $themeId, $force)
    {
        file_put_contents(storage_path() . '/logs/ExecCommandHandler-installTheme-0-' . microtime(true) . '-' . mt_rand()  . '.txt', print_r($themeId, true), FILE_APPEND | LOCK_EX);
        $installThemeExitCode = Artisan::call('theme-store:theme:install', [
            'theme_location' => $themeLocation,
            'theme_id' => $themeId,
            'layout' => 'blade',
            '--force' => $force,
        ]);
        file_put_contents(storage_path() . '/logs/ExecCommandHandler-installTheme-1-' . microtime(true) . '-' . mt_rand()  . '.txt', print_r($themeId, true), FILE_APPEND | LOCK_EX);

        if ($installThemeExitCode !== 0) {
            abort(500, 'Install theme failed.');
        }
    }

2、查看生成的日志文件,以确认命令已经执行完毕。确认命令未执行完成,因为未生成 ExecCommandHandler-installTheme-1- 的日志文件。如图1

查看生成的日志文件,以确认命令已经执行完毕。确认命令未执行完成,因为未生成 ExecCommandHandler-installTheme-1- 的日志文件
图1
Plaintext

/var/www/object/storage/logs # ls -l
total 4
-rw-r--r--    1 www      www             36 Aug 16 09:56 ExecCommandHandler-installTheme-0-1660643779.8784-1362478949.txt
/var/www/object/storage/logs # 

3、决定在容器中手动执行命令行,执行失败。如图2

决定在容器中手动执行命令行,执行失败
图2
Plaintext

/var/www/object # php artisan theme-store:theme:install /var/www/object/storage/ap
p/theme_downloads/2022/08/16/1660643779.663.1639598452 9708e042-0b71-4667-87da-0
738232afb35 blade --force
安装主题到数据仓库
安装失败,因为: SQLSTATE[22032]: <>: 3140 Invalid JSON text: "Missing a name for object member." at position 168 in value for column 'theme_asset.schema'. (SQL: insert into `theme_asset` (`asset_key`, `theme_id`, `mime_type`, `created_at`, `content`, `schema`, `category`, `updated_at`) values (apps/internal/comment/blocks/comment.blade.php, 9708e042-0b71-4667-87da-0738232afb35, text/html, 2022-08-16 10:12:52, @php
  $enable = $product[\'review_status\'] === \'open\';
@endphp

@if($enable)
  

  @script
    
  @endScript

  
    
      {{ \'comment.customer_review\' | t }}
    
    
      
        
          {!! str_repeat(\' \', 6) !!}
          
            
            
          
        
        
          @for ($i = 0; $i < 5; $i++)
          
          @endFor
        
      
      
        
      
    
  
@endif



, {
  "name": "商品评论",
  "target": "section",
  "templates": ["product_detail"],
  "available_if": "{{ is_module_enabled('Comment') }}",
  "javascript": "app.js",
}, app_block, 2022-08-16 10:12:52))
/var/www/object # 

4、根源在于命令行执行失败,并未抛出异常。如果抛出异常,则任务队列就不会一直进行中,也会自动失败。决定在本地 Windows 10 环境下复现此问题。如图3

根源在于命令行执行失败,并未抛出异常。如果抛出异常,则任务队列就不会一直进行中,也会自动失败。决定在本地 Windows 10 环境下复现此问题
图3
Plaintext

PS E:\wwwroot\object> php artisan theme-store-db:theme:install E:\wwwroot\object\storage\app\theme_downloads\2022\11\07\v2.0.0-rc.47 97af8c54-af1c-4f49-8d32-f603eb968078 blade --force
硬删除主题
安装主题到数据仓库
安装失败,因为: SQLSTATE[22032]: <>: 3140 Invalid JSON text: "Missing a name for object member." at position 168 in value for column 'theme_asset2.schema'. (SQL: insert into `theme_asset2` (`asset_key`, `theme_id`, `mime_type`, `created_at`, `content`, `schema`, `category`, `updated_at`) values (apps/internal/comment/blocks/comment.blade.php, 97af8c54-af1c-4f49-8d32-f603eb968078, text/html, 2022-11-07 06:41:25, @php
  $enable = $product[\'review_status\'] === \'open\';
@endphp

@if($enable)
  

  @script
    
  @endScript

  
    
      {{ \'comment.customer_review\' | t }}
    
    
      
        
          {!! str_repeat(\' \', 6) !!}
          
            
            
          
        
        
          @for ($i = 0; $i < 5; $i++)
          
          @endFor
        
      
      
        
      
    
  
@endif



, {
  "name": "商品评论",
  "target": "section",
  "templates": ["product_detail"],
  "available_if": "{{ is_module_enabled('Comment') }}",
  "javascript": "app.js",
}, app_block, 2022-11-07 06:41:25))
PS E:\wwwroot\object>

5、决定在队列中复现此问题,输出 $installThemeExitCode,无输出,原因是代码已经在 Artisan::call 时中断了,且未抛出异常。

PHP

        $themeLocation = 'E:\wwwroot\object\storage\app\theme_downloads\2022\11\07\v2.0.0-rc.47';
        $installThemeExitCode = Artisan::call('theme-store-db:theme:install', [
            'theme_location' => $themeLocation,
            'theme_id' => $themeId,
            'layout' => 'blade',
            '--force' => $force,
        ]);

        Log::info('installThemeExitCode', ['installThemeExitCode' => $installThemeExitCode]);

6、查看对应命令行的具体实现,其已经捕获了异常,然后 exit(1);。exit — 输出一个消息并且退出当前脚本。如果 status 是一个 int,该值会作为退出状态码,并且不会被打印输出。

PHP

        DB::beginTransaction();
        try {
            if ($purgeExisting) {
                $this->info("硬删除主题");
                $installer->purgeTheme($themeId);
            }
            $this->info("安装主题到数据仓库");

            $installer->install($themeLocation, $themeId);

            $this->info(sprintf("主题%s安装成功", $themeId));

            DB::commit();
        } catch(\Exception $exception) {
            DB::rollBack();

            $this->error(sprintf("安装失败,因为: %s", $exception->getMessage()));

            exit(1);
        }

7、将 exit(1); 修改为 return 1;。当命令运行失败后,返回 1。但是未获取到更为具体的失败原因。如图4

将 exit(1); 修改为 return 1;。当命令运行失败后,返回 1。但是未获取到更为具体的失败原因
图4
PHP

		DB::rollBack();

		$this->error(sprintf("安装失败,因为: %s", $exception->getMessage()));

		exit(1);

8、调整调用处的代码,当退出码不等于 0 时,获取上次运行命令的输出做为失败的原因。虽然包含了 info、error 等输出,期望的是仅获取 error 的输出,但是可以接受。如图5

调整调用处的代码,当退出码不等于 0 时,获取上次运行命令的输出做为失败的原因。虽然包含了 info、error 等输出,期望的是仅获取 error 的输出,但是可以接受。
图5
PHP

        if ($installThemeExitCode !== 0) {
            abort(500, Artisan::output());
        }

9、在终端中执行命令没有受到影响。不论是成功的还是失败的执行。

Plaintext

PS E:\wwwroot\object> php artisan theme-store-db:theme:install E:\wwwroot\object\storage\app\theme_downloads\2022\11\07\v2.0.0-rc.47 97af8c54-af1c-4f49-8d32-f603eb968078 blade --force
安装主题到数据仓库
安装失败,因为: SQLSTATE[22032]: <>: 3140 Invalid JSON text: "Missing a name for object member." at position 168 in value for column 'theme_asset2.schema'. (SQL: insert into `theme_asset2` (`asset_key`, `theme_id`, `mime_type`, `created_at`, `content`, `schema`, `category`, `updated_at`) values (apps/internal/comment/blocks/comment.blade.php, 97af8c54-af1c-4f49-8d32-f603eb968078, text/html, 2022-11-08 08:54:17, @php
  $enable = $product[\'review_status\'] === \'open\';
@endphp

@if($enable)
  

  @script
    
  @endScript

  
    
      {{ \'comment.customer_review\' | t }}
    
    
      
        
          {!! str_repeat(\'&          
            
            
          
        
        
          @for ($i = 0; $i < 5; $i++)
          
          @endFor
        
      
      
        
      
    
  
@endif



, {
  "name": "商品评论",
  "target": "section",
  "templates": ["product_detail"],
  "available_if": "{{ is_module_enabled('Comment') }}",
  "javascript": "app.js",
}, app_block, 2022-11-08 08:54:17))
PS E:\wwwroot\object> php artisan theme-store-db:theme:install E:\wwwroot\object\storage\app\theme_downloads\2022\11\04\1667531626.6087.1076713860 97af8c54-af1c-4f49-8d32-f603eb968078 blade --force
安装主题到数据仓库
主题97af8c54-af1c-4f49-8d32-f603eb968078安装成功
PS E:\wwwroot\object>

10、当在队列中,对应的 call 命令行内部抛出异常时,队列能够捕获到。如图5

PHP / Laravel / Yii2 老项目维护与长期技术支持

如果你的 PHP / Laravel / Yii2 项目已经上线,但遇到原开发离职、Bug 长期无人修复、接口不稳定、性能下降、代码难以接手等问题,可以联系我做一次远程技术排查。

适合以下情况:
✅ 老旧 PHP 系统无人维护
✅ Laravel / Yii2 项目 Bug 修复
✅ 后台管理系统小功能迭代
✅ RESTful API 接口排查
✅ MySQL / Redis / Nginx 性能问题
✅ 长期远程兼职维护

可先从一次小问题开始:
✅ 线上报错排查
✅ 接口异常分析
✅ 慢查询与性能瓶颈定位
✅ 代码结构初步评估
✅ 部署环境与日志检查

如需咨询,请联系我,并注明:PHP 维护咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

评论

2 条对“在 Linux 、Laravel 6 中,任务队列一直运行中的排查分析(已经设置超时时间)”的回复

  1. […] 在 Linux 、Laravel 6 中,任务队列一直运行中的排查分析(已经设置超时时间) […]

  2. […] Reference: Troubleshooting analysis of a Laravel 6 job queue stuck in a running state on Linux (timeout already…. The previous cause was that executing Artisan::call did not return 1 from the command line, which […]