如何通过另一个PHP脚本检测exec执行的大文件解压进程是否完成?
实现后台解压进程的状态检测
首先需要调整你的解压脚本,让unzip命令在后台运行(否则原脚本会阻塞到解压完成,die不会提前执行),同时通过标记文件或**进程ID(PID)**来记录解压状态,方便检测脚本判断。
方案一:用标记文件检测(推荐,更可靠)
步骤1:修改原解压脚本
调整exec命令,让解压后台执行,且仅在解压成功完成后生成一个标记文件:
// 先对路径参数做转义,防止命令注入 $zipPath = escapeshellarg($path . 'exports/' . $dir . '/' . $file); $targetDir = escapeshellarg($path . 'exports/' . $dir . '_work/'); $doneFlag = escapeshellarg($targetDir . '/unzip_success'); // 后台执行unzip,成功则生成标记文件,同时重定向日志到文件便于排查问题 exec("unzip $zipPath -d $targetDir > $targetDir/unzip.log 2>&1 && touch $doneFlag &"); die('UNPACKING STARTED');
步骤2:编写检测脚本
独立的PHP脚本通过检查标记文件是否存在来判断状态:
// 替换为实际的目标目录路径 $targetDir = $path . 'exports/' . $dir . '_work/'; $doneFlagPath = $targetDir . '/unzip_success'; if (file_exists($doneFlagPath)) { echo '解压已成功完成'; } else { // 可以额外检查解压目录是否有文件,判断是否在进行中 $hasFiles = count(scandir($targetDir)) > 2; // 排除.和.. echo $hasFiles ? '解压进行中' : '解压尚未开始或异常终止'; }
方案二:用进程ID(PID)检测
如果需要更实时的进程状态,可记录解压进程的PID,通过检查PID是否存活判断。
步骤1:修改原解压脚本
执行解压时记录PID到文件,解压完成后删除PID文件:
$zipPath = escapeshellarg($path . 'exports/' . $dir . '/' . $file); $targetDir = escapeshellarg($path . 'exports/' . $dir . '_work/'); $pidFile = escapeshellarg($path . 'exports/' . $dir . '_unzip.pid'); // 后台执行unzip,记录PID,完成后删除PID文件 exec("unzip $zipPath -d $targetDir > $targetDir/unzip.log 2>&1 && rm -f $pidFile & echo $! > $pidFile"); die('UNPACKING STARTED');
步骤2:编写检测脚本
读取PID文件,检查对应进程是否存活:
$pidFilePath = $path . 'exports/' . $dir . '_unzip.pid'; if (!file_exists($pidFilePath)) { echo '解压已完成'; } else { $pid = trim(file_get_contents($pidFilePath)); // 检查PID对应的进程是否存在(Linux环境) $processExists = exec("ps -p $pid > /dev/null 2>&1; echo $?"); if ($processExists == 0) { echo '解压进行中'; } else { // 进程已终止但PID文件未删除,清理文件并标记状态 unlink($pidFilePath); echo '解压已完成(或进程异常终止)'; } }
关键注意事项
- 必须使用
escapeshellarg()处理所有路径参数,避免命令注入漏洞,这是原代码的潜在风险。 - 后台执行命令必须加
&,否则原脚本会阻塞到解压结束,失去异步执行的意义。 - 标记文件方案比PID方案更可靠:如果解压进程异常崩溃,PID文件可能残留,而标记文件仅在解压成功时才会生成。
内容的提问来源于stack exchange,提问作者user3022527
相关产品推荐
相关产品推荐

