Windows CLI循环调用PHP脚本速度过慢,求多进程非阻塞解决方案
首先,咱们先拆解下你遇到的核心问题:单独跑subtask.bat只要2秒,但被task.bat调用(尤其是通过任务计划程序启动时)却要30秒,大概率是路径解析错误或者环境变量差异导致的,再加上可能的命令用法小问题,咱们一步步来解决:
一、排查最可能的原因:路径与环境变量问题
1. 相对路径的坑
你subtask.bat里用了../public/index.php这个相对路径,当task.bat被任务计划程序启动时,它的工作目录大概率不是你预期的目录(比如任务计划程序默认工作目录是C:\Windows\System32),这会导致PHP找不到要执行的脚本,一直在等待超时(通常就是30秒左右的默认超时时间)。
解决办法:把相对路径改成绝对路径,比如:
%PHP_PATH%\php.exe -c %PHP_INI_PATH%\php.ini "D:/your-project-root/public/index.php" --method="POST" --uri="/cron/sync" --header="Content-Type:application/json" --body="{\"offset\":\"0\",\"count\":\"1\",\"type\":\"TYPE1\"}"
2. 环境变量未正确加载
任务计划程序如果用系统账户运行,不会加载当前用户的环境变量,所以%PHP_PATH%和%PHP_INI_PATH%可能无法被正确解析,导致PHP启动失败或者找不到配置文件,进而超时。
解决办法:直接用绝对路径替换环境变量,比如:
"C:/php-8.2/php.exe" -c "C:/php-8.2/php.ini" "D:/your-project-root/public/index.php" --method="POST" --uri="/cron/sync" --header="Content-Type:application/json" --body="{\"offset\":\"0\",\"count\":\"1\",\"type\":\"TYPE1\"}"
二、优化start命令的用法
你当前的start "" /MIN "subtask.bat"如果subtask.bat不在task.bat的工作目录里,可能会出现启动失败或者找不到文件的情况,建议改成更稳妥的写法:
@start "" /MIN cmd /c "D:/path-to-your-bat/subtask.bat"
这样可以确保系统能正确定位到subtask.bat的位置,避免因为路径问题导致的隐性超时。
三、验证子任务是否真的在并行运行
你当前的start命令已经是启动新进程了,所以循环不会被单个子任务阻塞,但如果子任务因为路径问题卡住,就会看起来整个流程变慢。可以在subtask.bat开头加一行日志,验证每个子任务的启动时间:
echo Subtask started at %time% >> D:/cron-logs/subtask-log.txt "C:/php-8.2/php.exe" -c "C:/php-8.2/php.ini" "D:/your-project-root/public/index.php" --method="POST" --uri="/cron/sync" --header="Content-Type:application/json" --body="{\"offset\":\"0\",\"count\":\"1\",\"type\":\"TYPE1\"}" echo Subtask ended at %time% with error code %errorlevel% >> D:/cron-logs/subtask-log.txt exit 0
通过日志可以清楚看到每个子任务的耗时和返回码,判断是PHP脚本本身慢,还是启动过程慢。
四、优化循环等待的准确性
你用ping 127.0.0.1 -n 6 > nul来实现等待,但这个命令实际等待的是5秒(因为-n参数是发送的包数,间隔1秒,6个包之间有5个间隔),如果要准确等待6秒,建议用timeout命令:
@timeout /t 6 /nobreak > nul
这个命令更可靠,不会因为系统ping的设置差异导致等待时间不准。
五、额外排查点:网络/权限问题
如果上面的修改后还是慢,那可能是PHP脚本本身的问题:
- 任务计划程序的运行账户可能没有访问MySQL数据库或者外部curl服务的权限,导致脚本卡在网络请求上;
- 可以在任务计划程序里设置**“不管用户是否登录都要运行”,同时勾选“最高权限运行”**,避免权限不足的问题;
- 测试直接在任务计划程序里运行subtask.bat,看是否还是慢,如果是,那问题就出在PHP脚本的网络/数据库连接上,需要排查MySQL和外部服务的访问延迟。
内容的提问来源于stack exchange,提问作者LazNiko

