PHP脚本执行后自动重启:解决分页API请求504超时问题
老哥,手动跑12次脚本确实够折腾的!我给你几个实用的方案,帮你实现脚本自动续跑,彻底解放双手😎
方案1:状态持久化+自动重启(最适合web/CLI混合场景)
核心思路是把当前要处理的页码存到一个文件(或者Redis、数据库)里,脚本每次启动先读这个状态,处理完N页后更新状态,再自动启动下一次脚本运行——这样单次脚本的运行时间被拆分,不会触发服务器504超时。
具体步骤:
- 先创建一个状态文件(比如
page_state.txt),初始内容写1(表示从第1页开始)。 - 改造你的PHP脚本,逻辑如下:
- 读取状态文件里的起始页码
- 设置单次脚本处理的页数(比如
$pagesPerRun = 2,根据API响应速度调整,确保单次运行不超时) - 循环处理这批页码
- 处理完后计算下一批起始页码,更新状态文件
- 如果还有未处理的页,就通过shell命令启动下一次脚本运行
代码示例:
<?php // 状态文件路径,根据你的实际位置调整 $stateFile = __DIR__ . '/page_state.txt'; // 单次处理的页数,按需调整 $pagesPerRun = 2; // 先获取API的总页数(你需要实现这个函数,请求一次首页拿到总页数) $totalPages = getTotalPagesFromApi(); // 读取当前起始页码 $startPage = file_exists($stateFile) ? (int)file_get_contents($stateFile) : 1; if ($startPage === 1) { file_put_contents($stateFile, $startPage); } // 计算本次处理的结束页码(不超过总页数) $endPage = min($startPage + $pagesPerRun - 1, $totalPages); // 批量处理页码 for ($page = $startPage; $page <= $endPage; $page++) { echo "正在处理第{$page}页...\n"; // 替换成你的curl请求逻辑 $response = fetchApiPage($page); // 替换成你的数据处理逻辑(存库/写文件等) processResponseData($response); } // 准备下一次运行的起始页 $nextStartPage = $endPage + 1; if ($nextStartPage <= $totalPages) { // 更新状态文件 file_put_contents($stateFile, $nextStartPage); // 后台启动下一次脚本运行(注意PHP CLI路径,比如/usr/bin/php) exec('php ' . __FILE__ . ' > /dev/null 2>&1 &'); echo "已调度下一次运行,起始页:{$nextStartPage}\n"; } else { // 所有页处理完成,删除状态文件 unlink($stateFile); echo "所有页码处理完成!🎉\n"; } // 辅助函数示例,按需修改 function getTotalPagesFromApi() { $ch = curl_init('https://你的API地址?page=1'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $resp = curl_exec($ch); curl_close($ch); $data = json_decode($resp, true); return $data['total_pages'] ?? 12; // 替换成你API返回的总页数字段 } function fetchApiPage($page) { $ch = curl_init("https://你的API地址?page={$page}"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $resp = curl_exec($ch); curl_close($ch); return json_decode($resp, true); } function processResponseData($data) { // 这里写你的数据处理逻辑,比如插入数据库 // ... } ?>
注意:如果是在服务器上运行,要确保PHP允许执行shell命令,并且php命令的路径正确(可以用which php查看绝对路径)。> /dev/null 2>&1 &是让脚本在后台运行,不占用当前终端。
方案2:Shell脚本循环调用(适合纯CLI环境)
如果你的服务器允许用命令行运行脚本,这个方案更简单——直接写个shell脚本,循环调用你的PHP脚本,每次传入不同的页码参数。
步骤:
- 改造PHP脚本,让它接受命令行参数传入页码:
<?php // 从命令行获取当前页码($argv[0]是脚本文件名,$argv[1]是第一个参数) $currentPage = $argv[1] ?? 1; echo "处理第{$currentPage}页...\n"; // 你的curl请求和数据处理逻辑 // ... ?>
- 写一个shell脚本(比如
run_api.sh):
#!/bin/bash # 总页数,根据你的实际情况修改 total_pages=12 # 循环调用PHP脚本 for ((page=1; page<=total_pages; page++)) do echo "启动处理第${page}页" php 你的脚本文件名.php $page # 可选:每次请求后暂停1秒,避免给API造成过大压力 sleep 1 done echo "所有页码处理完成!"
- 给shell脚本加执行权限:
chmod +x run_api.sh
- 运行脚本:
./run_api.sh
这个方案的好处是完全避开web服务器的超时限制,因为CLI模式下PHP默认没有执行时间限制(也可以在PHP脚本里加set_time_limit(0)确保不会超时)。
方案3:消息队列(适合大规模/高可靠性场景)
如果你的数据量极大,或者需要处理失败自动重试的机制,可以用消息队列(比如Redis队列、RabbitMQ)。先把所有要处理的页码加入队列,然后启动多个脚本消费者来处理队列任务。不过这个方案稍微复杂一点,适合有一定架构基础的场景。
额外提醒
- 加重试机制:给API请求加重试逻辑,比如某一页请求失败(500/超时),重试2-3次,避免单次失败中断整个流程。
- 日志记录:每处理一页都记录日志(比如写入日志文件),方便后续排查问题。
- CLI优先:尽量用CLI模式运行脚本,web环境的超时限制很容易触发504,CLI模式更稳定。
内容的提问来源于stack exchange,提问作者Alex Baur
相关产品推荐
相关产品推荐

