long polling实现Telegram板球比分机器人触发Maximum execution time exceed报错如何解决
问题原因分析
首先梳理你现有代码的核心问题:
- 执行环境问题:如果是通过web服务器(Nginx/Apache)运行该PHP脚本,PHP默认配置的
max_execution_time(通常为30秒)会限制脚本运行时长,死循环运行几十秒就会触发Maximum execution time exceed报错。 - 逻辑错误:你先将
$_SESSION["score"]赋值为当前比分,再判断二者是否不等,这个条件永远为假,根本不会触发消息发送。 - 存储介质错误:session是面向web端单用户请求的临时存储,不仅CLI模式下无法使用,而且单次脚本结束后session就会失效,根本无法存储上一次请求的比分数据。
- 缺少异常处理:
file_get_contents请求第三方API没有超时、错误捕获逻辑,一旦API超时或响应异常,会直接导致脚本崩溃。
最优实现方案
有两种成熟方案可选,可根据你的运维习惯选择:
方案1:CLI常驻进程方案(适合低延迟推送)
改用PHP CLI模式运行脚本,CLI模式默认关闭最大执行时间限制,不会触发超时错误,搭配缓存存储历史比分即可实现需求。
修正后代码示例
<?php $token = 'xyz'; $group_name = 'xyz'; // 用本地文件存储上一次的比分,也可以替换为Redis等缓存 $scoreCacheFile = __DIR__ . '/last_score.txt'; while(true){ // 给HTTP请求加5秒超时配置,避免被卡住 $context = stream_context_create([ 'http' => [ 'timeout' => 5 ] ]); try { $ipl = @file_get_contents('https://cricket-api.vercel.app/cri.php?url=https://www.cricbuzz.com/live-cricket-scores/38708/rocks-vs-war-pool-d-csa-provincial-t20-cup-2021', false, $context); if (!$ipl) throw new Exception('赛事API请求失败'); $ipl_data = json_decode($ipl, true); if (!isset($ipl_data['livescore']['current'])) throw new Exception('比分解析失败'); $current_score = $ipl_data['livescore']['current']; // 读取上一次存储的比分 $last_score = file_exists($scoreCacheFile) ? file_get_contents($scoreCacheFile) : ''; // 比分不一致才发送消息 if ($current_score != $last_score) { // 对内容做urlencode,避免特殊字符导致Telegram接口请求失败 $sendUrl = "https://api.telegram.org/bot{$token}/sendMessage?chat_id={$group_name}&text=" . urlencode($current_score); @file_get_contents($sendUrl, false, $context); // 更新存储的最新比分 file_put_contents($scoreCacheFile, $current_score); } } catch (Exception $e) { // 可自行添加错误日志记录逻辑 } sleep(10); } ?>
运行方式
在服务器终端执行php 你的脚本文件名.php即可,需要后台运行的话可以用nohup或者systemd托管进程,避免终端关闭后脚本停止。
方案2:定时任务方案(稳定性更高)
如果不想维护常驻进程,可以用Linux系统的crontab定时任务执行脚本,去掉死循环,每次脚本执行完就退出,完全不会有超时问题:
- 把上述代码中的
while(true)和sleep(10)逻辑删除 - 配置crontab,每分钟执行6次脚本(间隔10秒),配置示例:
* * * * * php /path/to/your/script.php * * * * * sleep 10; php /path/to/your/script.php * * * * * sleep 20; php /path/to/your/script.php * * * * * sleep 30; php /path/to/your/script.php * * * * * sleep 40; php /path/to/your/script.php * * * * * sleep 50; php /path/to/your/script.php
这种方案的优势是脚本不需要一直挂着,就算某次执行崩溃了下次还会自动执行,运维成本更低。
内容的提问来源于stack exchange,提问作者Shakti Goyal
相关产品推荐
相关产品推荐

