ThinkPHP6定时任务需手动捕获异常并通知,推荐在命令类execute()中用try-catch包裹业务代码,调用封装的多通道通知服务;HTTP触发方式可在行为类中统一拦截;系统级日志+外部监控可作补充。

ThinkPHP6 本身不内置异常告警机制,定时任务出错默认静默失败。要实现异常告警通知(如邮件、钉钉、企业微信、短信),关键是在任务执行环节捕获异常,并主动触发通知逻辑,而不是依赖框架自动上报。
在命令行任务中统一捕获并发送告警
这是最推荐的方式——把告警逻辑内聚到每个自定义命令里,确保每次执行都具备容错和通知能力。
- 在 app/command/YourTask.php 的
execute()方法中,用try...catch包裹全部业务代码 - 捕获
\Throwable(覆盖所有错误和异常),记录详细日志(含堆栈) - 调用你封装好的通知服务,比如:
NoticeService::sendDingTalk('定时任务【mytask】执行失败:' . $e->getMessage(), $e->getTraceAsString()) - 建议将通知服务单独抽成类(如
app/service/NoticeService.php),支持多通道配置与开关控制
使用统一的异常拦截中间件(适用于 HTTP 触发型任务)
如果你采用「内置行为扩展模拟 Cron」方式(通过用户访问触发检查),可在行为类中统一加告警:
- 在
app/behavior/CronRun.php的run()方法里,对每个待执行任务做 try/catch 包裹 - 失败时调用
Log::error()记录,并同步触发通知(注意避免重复告警,可加 Redis 锁或时间窗口去重) - 该方式适合无服务器权限的共享主机环境,但依赖真实访问流量,不适合强时效性任务
结合系统级日志 + 外部监控告警
作为补充手段,不侵入代码也能快速落地:
立即学习“PHP免费学习笔记(深入)”;
- 让 Crontab 执行命令时重定向 stderr 到日志文件,例如:
* * * * * cd /path && php think mytask 2>> runtime/log/cron-error.log - 用 Logrotate 或脚本定期扫描该日志文件,发现 ERROR/Exception 关键字后调用 curl 发送钉钉 Webhook
- 或接入专业监控工具(如 Prometheus + AlertManager、Sentry),通过采集
runtime/log/下的日志实现告警闭环
注意事项
避免几个常见坑:
- 不要在 catch 块里只写
echo或dump()—— Crontab 下这些输出不可见,也无法触发通知 - 通知服务本身要健壮:网络超时需设
timeout=5,失败应降级为本地日志,防止告警逻辑自身崩溃导致漏报 - 高频任务(如秒级)务必加告警频率限制,比如“10分钟内同类型错误最多告警1次”,避免消息轰炸
- 敏感信息(如数据库密码、API密钥)禁止硬编码进通知内容,可用
Log::record()记录脱敏后的上下文



















