php artisan命令因注册自定义SchedulerDaemon命令无响应求助
故障原因
- 语法错误:
SchedulerDaemon类末尾多了一个多余的闭合大括号,导致PHP解析代码时抛出致命语法错误。Laravel启动时会自动加载$commands数组中注册的所有命令类,语法错误直接导致整个应用(包括artisan命令、web服务)无法正常启动,无任何响应。
- 语法错误:
- 逻辑错误1:
updateBookings方法中的if判断未加花括号,仅$stoppedAt = null属于if判断的执行分支,后续的try/catch代码无论时间是否匹配7:00/10:00都会执行;且如果时间不匹配if条件,$stoppedAt变量未定义,catch块中访问$stoppedAt->email会抛出未定义变量错误。
- 逻辑错误1:
- 逻辑错误2:时间格式化使用12小时制格式
h:i,会导致下午19:00也匹配07:00的条件,出现非预期的重复执行。
- 逻辑错误2:时间格式化使用12小时制格式
- 若你将该常驻命令配置到web服务启动流程中,命令内部的无限递归+sleep逻辑会阻塞web进程,导致服务无响应。
解决方案
- 修复语法错误:删除
SchedulerDaemon类末尾多余的那个闭合大括号,保证类的大括号配对正确。
- 修复语法错误:删除
- 修正
updateBookings的逻辑:
- 修正
private function updateBookings() { // 提前定义变量,避免未定义错误 $stoppedAt = null; // 改用24小时制格式H:i,避免12小时制的匹配错误 if (Carbon::now()->timezone('Asia/Manila')->format('H:i') == '07:00' || Carbon::now()->timezone('Asia/Manila')->format('H:i') == '10:00') { try { $bookings = Booking::where('pickup_date', '=', Carbon::now()->timezone('Asia/Manila')->format('Y-m-d')) ->where('status', '=', '2') ->get(); Log::info($bookings); foreach ($bookings as $b) { DB::beginTransaction(); Mail::send( 'templates.emails.pickup', ['booking' => $b, 'status' => 'pickup'], function ($m) use ($b) { $m->from('no-reply@kane.com'); $m->to($b->user->email, $b->user->getName()) ->subject('Pick up Status'); } ); $b->status = 3; $b->save(); $stoppedAt = $b->user; DB::commit(); } ActivityLog::log('Updating all bookings with pick up date set for today.', 0); ActivityLog::log('Sending emails to all clients with pick up date set for today.', 0); } catch (Exception $e) { // 增加变量存在判断,避免空对象报错 $errMsg = $stoppedAt ? 'Daily booking update and mailing task failed (stopped at '.$stoppedAt->email.'): '.$e->getMessage() : 'Daily booking update and mailing task failed: '.$e->getMessage(); ActivityLog::log($errMsg, 0); Log::error($e); DB::rollback(); } } }
- 单独启动调度常驻进程:该命令是常驻后台的进程,不要和web服务的启动流程绑定,单独使用
php artisan schedule:cron命令启动即可。如果使用Heroku等平台,在Procfile中配置独立的worker进程运行该命令,不要占用web进程资源。
- 单独启动调度常驻进程:该命令是常驻后台的进程,不要和web服务的启动流程绑定,单独使用
- 确认Kernel中
$commands数组的注册代码取消注释:
- 确认Kernel中
protected $commands = [ Commands\SchedulerDaemon::class ];
内容的提问来源于stack exchange,提问作者Virus5600
相关产品推荐
相关产品推荐

