PHP exec创建的parallel待处理任务排队位置及手动终止方法
问题原理说明
你遇到的现象是GNU Parallel的自带调度机制导致的,和PHP、Apache无关:
- 你执行的命令会先把
ls输出的所有匹配文件列表通过管道传给parallel,parallel会将全部待处理任务加载到自身的内存队列中,再按照-j8的配置固定同时运行8个任务,每跑完一个就从队列中取下一个执行,直到所有任务处理完成 - 你终止PHP脚本、关闭浏览器时,系统默认只会终止PHP自身的exec父进程,已经启动的parallel进程会被系统收为孤儿进程继续后台运行,它内存中的待处理队列不会被清空,因此会持续生成PDF直到所有任务跑完
- 这些待处理任务没有持久化存储在磁盘的固定位置,全部存放在运行中的parallel进程的内存里,所以你执行ps命令只能看到当前正在运行的8个tesseract进程,看不到排队的待处理任务
终止所有相关任务的操作步骤
- 首先找到正在运行的parallel主进程PID
执行命令:ps aux | grep parallel | grep tesseract
找到对应的进程PID后,执行终止命令,比如PID为1234时:kill 1234
如果进程无响应,可以强制终止:kill -9 1234 - 清理当前正在运行的tesseract子进程
执行命令:pkill -f "tesseract.*pdf" - 验证终止结果
执行命令确认没有遗留相关进程:ps aux | grep -E 'parallel|tesseract'
无匹配输出即说明所有任务已终止
后续管控方案
可以通过修改配置避免后续再出现同类问题:
- 给parallel添加信号传递参数:执行parallel时加上
--termseq INT,TERM,KILL,200参数,当parallel的父进程(你的PHP脚本)被终止时,parallel会收到信号自动终止所有子进程并清空任务队列,修改后的代码参考:
exec("ls $image_subdir | parallel --termseq INT,TERM,KILL,200 -j8 tesseract $image_subdir/{} /Processed/OCR/{.} -l eng pdf",$output, $result_code);
- 增加全局执行超时限制:可以在parallel外层套
timeout工具限制最大运行时长,比如设置最多运行1小时自动终止:timeout 3600 parallel ...... - 在PHP中注册退出清理回调:通过
register_shutdown_function注册脚本退出时的回调逻辑,主动终止parallel和tesseract相关进程
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

