You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过PHP终止exec()启动运行的bash脚本进程?

实现方案

你当前的写法存在两个核心问题,导致无法实现中途终止:一是exec()是同步阻塞调用,PHP会一直等待脚本全量执行完成才会返回响应,前端全程处于等待状态;二是执行脚本时没有记录进程ID,也没有做进程组隔离,后续无法定位要终止的进程,也没法一次性清掉脚本启动的所有子进程(Java进程、数据库操作进程等)。
按以下步骤改造即可:

1. 改造脚本启动逻辑

不要直接把替换完参数的脚本内容拼接到bash -c参数里,特殊字符过多很容易出现转义异常。改成生成临时执行脚本,通过setsid启动独立进程组后台运行,同时记录进程ID、临时文件路径到用户会话,方便后续终止和清理。
替换display.php里的原有执行逻辑:

if( isset($_POST["submitPara"]) ){
    session_start();
    $runningOcc = $_POST["runningOcc"];
    // 生成唯一临时脚本,避免多用户并发冲突
    $tmpScriptPath = tempnam(sys_get_temp_dir(), 'task_');
    $scriptContent = file_get_contents('myscript.sh');
    $scriptContent = str_replace("Occur_Run", $runningOcc, $scriptContent);
    file_put_contents($tmpScriptPath, $scriptContent);
    chmod($tmpScriptPath, 0755);

    // 初始化日志文件存储脚本输出
    $logPath = tempnam(sys_get_temp_dir(), 'log_');
    // setsid启动独立进程组,后台运行,返回主进程PID
    $cmd = sprintf("setsid bash %s > %s 2>&1 & echo $!", $tmpScriptPath, $logPath);
    $pid = trim(exec($cmd));

    // 把任务信息存到会话,做用户级隔离
    $_SESSION['current_task'] = [
        'pid' => $pid,
        'script_path' => $tmpScriptPath,
        'log_path' => $logPath
    ];

    // 直接跳转,无需等待脚本执行完成
    header("Location: status.php");
    exit;
}

2. 新增任务终止接口

新建cancel.php文件,读取当前会话关联的任务PID,给整个进程组发送强制终止信号,清理临时文件后跳转回首页:

session_start();
if(isset($_SESSION['current_task'])){
    $pid = $_SESSION['current_task']['pid'];
    // 注意PID前的负号:表示杀死整个进程组,连带所有子进程一起终止,不会留孤儿进程
    exec(sprintf("kill -9 -%d 2>/dev/null", $pid));
    // 清理临时文件
    @unlink($_SESSION['current_task']['script_path']);
    @unlink($_SESSION['current_task']['log_path']);
    unset($_SESSION['current_task']);
}
header("Location: index.php");
exit;

3. 改造前端交互

你原本的取消按钮没有绑定任何事件,直接给它加跳转逻辑即可,修改index.php里的取消按钮代码:

<button type="button" name="Cancel" onclick="location.href='cancel.php'"> Cancel Running </button>

如果需要实时查看脚本输出,可以新建status.php做简单的日志轮询,不用等脚本全部执行完就能看到执行进度,任务执行过程中随时可以点取消按钮终止。

注意事项

  • 必须使用setsid启动进程组,杀进程时必须给PID加负号,否则脚本启动的Java、数据库相关子进程会留在后台继续运行,占用系统资源。
  • 任务信息存在用户会话中,天然做了多用户隔离,不会出现误杀其他用户任务的问题。
  • 保证PHP运行用户有临时目录读写权限、kill命令执行权限即可,不要给过高的系统权限。

内容的提问来源于stack exchange,提问作者sysSTD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:39:21