在 Linux 、Laravel 6 中,任务队列一直运行中的排查分析(已经设置超时时间)
1、在任务队列中 Artisan::call 了命令,代码如下
/**
* 执行安装主题命令
* @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
/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
/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]: <<Unknown error>>: 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)
<link rel=\"preload\" as=\"style\" onload=\"this.rel=\'stylesheet\'\" href=\"{{ \'app.css\' | theme_asset_url }}\">
@script
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%3E%0A%20%20%20%20%20%20Object.assign(window.plugins%2C%20%7B%0A%20%20%20%20%20%20%20%20comment%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20name%3A%20%5C'%7B%7B%20%40config(%5C'comment.name%5C')%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20template%3A%20%5C'%7B%7B%20%40config(%5C'comment.template%5C')%20%3F%3F%20%5C%22tile%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20count%3A%20%7B%7B%20%40config(%5C'comment.count%5C')%20%3F%3F%204%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20comment_time%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_time%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_country%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_country%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_account%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_account%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_fives_star%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_fives_star%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_four_star%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_four_star%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_counts%3A%20%7B%7B%20%40config(%5C'comment.comment_counts%5C')%20%3F%3F%200%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20translate%3A%20%5C'%7B%7B%20%40config(%5C'comment.translate%5C')%20%3F%3F%20%5C%22Y%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_template%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_template%5C')%20%3F%3F%20%5C%22tile%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_count%3A%20%7B%7B%20%40config(%5C'comment.store_count%5C')%20%3F%3F%20%5C'4%5C'%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20store_comment_time%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_comment_time%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_comment_country%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_comment_country%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_import%3A%20%40json(%40config(%5C'comment.comment_import%5C')%20%3F%3F%20%5B%5D)%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D)%0A%20%20%20%20%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
@endScript
<section class=\"section rendering\">
<h2 class=\"text-2xl text-center md:text-left font-normal leading-loose\">
{{ \'comment.customer_review\' | t }}
</h2>
<div class=\"flex flex-col items-center justify-start sm:flex-row md:justify-between mb-4 gap-4\">
<div class=\"sm:flex-1 flex-col flex sm:flex-row items-center\">
<div class=\"sm:inline-block max-w-[280px] inline-flex items-center py-2 grow\">
<div class=\"inline-block bg-slate-200 text-5xl sm:text-6xl sm:text-left text-center mr-1\">{!! str_repeat(\' \', 6) !!}</div>
<div class=\"w-1/2 sm:w-full text-left mt-2\">
<div class=\"h-5 w-24 bg-slate-200\"></div>
<div class=\"h-5 w-4/5 mt-1 bg-slate-200\"></div>
</div>
</div>
<ul class=\"inline-block\">
@for ($i = 0; $i < 5; $i++)
<li class=\"w-60 h-4 mb-1.5 bg-slate-200\"></li>
@endFor
</ul>
</div>
<div class=\"w-full sm:w-36\">
<div class=\"h-10 my-6 bg-slate-200\"></div>
</div>
</div>
</section>
@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
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]: <<Unknown error>>: 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)
<link rel=\"preload\" as=\"style\" onload=\"this.rel=\'stylesheet\'\" href=\"{{ \'app.css\' | theme_asset_url }}\">
@script
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%3E%0A%20%20%20%20%20%20Object.assign(window.plugins%2C%20%7B%0A%20%20%20%20%20%20%20%20comment%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20name%3A%20%5C'%7B%7B%20%40config(%5C'comment.name%5C')%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20template%3A%20%5C'%7B%7B%20%40config(%5C'comment.template%5C')%20%3F%3F%20%5C%22tile%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20count%3A%20%7B%7B%20%40config(%5C'comment.count%5C')%20%3F%3F%204%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20comment_time%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_time%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_country%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_country%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_account%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_account%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_fives_star%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_fives_star%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_four_star%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_four_star%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_counts%3A%20%7B%7B%20%40config(%5C'comment.comment_counts%5C')%20%3F%3F%200%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20translate%3A%20%5C'%7B%7B%20%40config(%5C'comment.translate%5C')%20%3F%3F%20%5C%22Y%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_template%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_template%5C')%20%3F%3F%20%5C%22tile%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_count%3A%20%7B%7B%20%40config(%5C'comment.store_count%5C')%20%3F%3F%20%5C'4%5C'%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20store_comment_time%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_comment_time%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_comment_country%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_comment_country%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_import%3A%20%40json(%40config(%5C'comment.comment_import%5C')%20%3F%3F%20%5B%5D)%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D)%0A%20%20%20%20%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
@endScript
<section class=\"section rendering\">
<h2 class=\"text-2xl text-center md:text-left font-normal leading-loose\">
{{ \'comment.customer_review\' | t }}
</h2>
<div class=\"flex flex-col items-center justify-start sm:flex-row md:justify-between mb-4 gap-4\">
<div class=\"sm:flex-1 flex-col flex sm:flex-row items-center\">
<div class=\"sm:inline-block max-w-[280px] inline-flex items-center py-2 grow\">
<div class=\"inline-block bg-slate-200 text-5xl sm:text-6xl sm:text-left text-center mr-1\">{!! str_repeat(\' \', 6) !!}</div>
<div class=\"w-1/2 sm:w-full text-left mt-2\">
<div class=\"h-5 w-24 bg-slate-200\"></div>
<div class=\"h-5 w-4/5 mt-1 bg-slate-200\"></div>
</div>
</div>
<ul class=\"inline-block\">
@for ($i = 0; $i < 5; $i++)
<li class=\"w-60 h-4 mb-1.5 bg-slate-200\"></li>
@endFor
</ul>
</div>
<div class=\"w-full sm:w-36\">
<div class=\"h-10 my-6 bg-slate-200\"></div>
</div>
</div>
</section>
@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 时中断了,且未抛出异常。
$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,该值会作为退出状态码,并且不会被打印输出。
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
DB::rollBack();
$this->error(sprintf("安装失败,因为: %s", $exception->getMessage()));
exit(1);
8、调整调用处的代码,当退出码不等于 0 时,获取上次运行命令的输出做为失败的原因。虽然包含了 info、error 等输出,期望的是仅获取 error 的输出,但是可以接受。如图5
if ($installThemeExitCode !== 0) {
abort(500, Artisan::output());
}
9、在终端中执行命令没有受到影响。不论是成功的还是失败的执行。
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]: <<Unknown error>>: 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)
<link rel=\"preload\" as=\"style\" onload=\"this.rel=\'stylesheet\'\" href=\"{{ \'app.css\' | theme_asset_url }}\">
@script
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%3E%0A%20%20%20%20%20%20Object.assign(window.plugins%2C%20%7B%0A%20%20%20%20%20%20%20%20comment%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20name%3A%20%5C'%7B%7B%20%40config(%5C'comment.name%5C')%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20template%3A%20%5C'%7B%7B%20%40config(%5C'comment.template%5C')%20%3F%3F%20%5C%22tile%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20count%3A%20%7B%7B%20%40config(%5C'comment.count%5C')%20%3F%3F%204%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20comment_time%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_time%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_country%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_country%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_account%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_account%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_fives_star%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_fives_star%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_four_star%3A%20%5C'%7B%7B%20%40config(%5C'comment.comment_four_star%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_counts%3A%20%7B%7B%20%40config(%5C'comment.comment_counts%5C')%20%3F%3F%200%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20translate%3A%20%5C'%7B%7B%20%40config(%5C'comment.translate%5C')%20%3F%3F%20%5C%22Y%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_template%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_template%5C')%20%3F%3F%20%5C%22tile%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_count%3A%20%7B%7B%20%40config(%5C'comment.store_count%5C')%20%3F%3F%20%5C'4%5C'%20%7D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20store_comment_time%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_comment_time%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20store_comment_country%3A%20%5C'%7B%7B%20%40config(%5C'comment.store_comment_country%5C')%20%3F%3F%20%5C%22no%5C%22%20%7D%7D%5C'%2C%0A%20%20%20%20%20%20%20%20%20%20comment_import%3A%20%40json(%40config(%5C'comment.comment_import%5C')%20%3F%3F%20%5B%5D)%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D)%0A%20%20%20%20%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
@endScript
<section class=\"section rendering\">
<h2 class=\"text-2xl text-center md:text-left font-normal leading-loose\">
{{ \'comment.customer_review\' | t }}
</h2>
<div class=\"flex flex-col items-center justify-start sm:flex-row md:justify-between mb-4 gap-4\">
<div class=\"sm:flex-1 flex-col flex sm:flex-row items-center\">
<div class=\"sm:inline-block max-w-[280px] inline-flex items-center py-2 grow\">
<div class=\"inline-block bg-slate-200 text-5xl sm:text-6xl sm:text-left text-center mr-1\">{!! str_repeat(\'& <div class=\"w-1/2 sm:w-full text-left mt-2\">
<div class=\"h-5 w-24 bg-slate-200\"></div>
<div class=\"h-5 w-4/5 mt-1 bg-slate-200\"></div>
</div>
</div>
<ul class=\"inline-block\">
@for ($i = 0; $i < 5; $i++)
<li class=\"w-60 h-4 mb-1.5 bg-slate-200\"></li>
@endFor
</ul>
</div>
<div class=\"w-full sm:w-36\">
<div class=\"h-10 my-6 bg-slate-200\"></div>
</div>
</div>
</section>
@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





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