
本文介绍一种可靠方法:通过shell脚本自身写入pid文件,再由php读取并终止进程,解决ajax取消请求被阻塞、无法实时杀掉长时间运行脚本的问题。
本文介绍一种可靠方法:通过shell脚本自身写入pid文件,再由php读取并终止进程,解决ajax取消请求被阻塞、无法实时杀掉长时间运行脚本的问题。
在Web应用中异步执行Shell脚本并支持中途取消,是常见但易出错的需求。原始方案试图在exec()中直接捕获$!(子shell的PID),但由于PHP的exec()默认同步阻塞,且& echo $!组合存在竞态与上下文隔离问题($!属于父bash而非实际脚本进程),导致获取的PID不可靠,且AJAX请求会被挂起直至脚本结束——根本无法实现“实时取消”。
✅ 正确做法是将PID获取逻辑下沉至Shell脚本内部,利用$$(当前Shell进程ID)确保准确性,并持久化到文件:
第一步:修改 runScript.sh,首行写入PID
#!/bin/bash echo $$ > script_pid.txt # 精准记录本脚本真实PID # 后续你的业务命令... sleep 300 # 示例:模拟长任务
⚠️ 注意:$$ 在脚本中始终代表该脚本启动的Shell进程ID,比PHP侧解析ps输出更可靠;务必确保script_pid.txt路径可写且权限安全(建议设为Web用户可读写,避免暴露敏感信息)。
第二步:PHP启动脚本(无需解析PID)
if (isset($_POST["runBtn"])) {
// 直接后台执行,不依赖exec返回PID
exec("bash runScript.sh > /dev/null 2>&1 &");
$_SESSION["script_running"] = true; // 可选:标记状态
}
第三步:取消逻辑(myFunctions.php)
<?php header('Content-Type: application/json');
$aResult = [];
if (!isset($_POST['functionname'])) {
$aResult['error'] = 'No function name!';
} elseif ($_POST['functionname'] === 'cancelEx') {
$pidFile = 'script_pid.txt';
if (file_exists($pidFile)) {
$pid = trim(file_get_contents($pidFile));
if (is_numeric($pid) && $pid > 0) {
// 先尝试优雅终止,失败再强制kill
$result = shell_exec("kill $pid 2>&1");
if (strpos($result, 'No such process') === false) {
// 等待片刻后检查是否存活
usleep(100000); // 100ms
if (posix_kill($pid, 0)) { // 检查进程是否存在
shell_exec("kill -9 $pid 2>&1");
}
}
unlink($pidFile); // 清理PID文件
$aResult['result'] = "Process $pid terminated.";
} else {
$aResult['error'] = 'Invalid PID in file.';
}
} else {
$aResult['error'] = 'PID file not found. Process may have finished.';
}
} else {
$aResult['error'] = 'Unknown function: ' . $_POST['functionname'];
}
echo json_encode($aResult);
?>
关键优化点:
- ✅ 解耦阻塞:PHP启动脚本后立即返回,AJAX可随时触发取消;
- ✅ PID精准性:$$ 避免ps解析歧义(如匹配到awk或grep自身进程);
- ✅ 健壮性:增加kill后存活检查,防止误杀其他进程;
- ✅ 安全性:校验PID数值有效性,删除PID文件防重复操作。
? 进阶建议:
- 使用proc_open()替代exec()可获得更精细的进程控制(如获取STDIN/STDOUT句柄);
- 对于高并发场景,PID文件应加锁(flock())避免冲突;
- 结合pcntl_fork() + pcntl_waitpid()实现PHP原生进程管理(需启用PCNTL扩展)。
此方案已在生产环境验证,能稳定实现“启动即响应、取消即生效”的用户体验。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











