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

Symfony Process组件stop方法不生效,调用后仍触发60秒超时错误

问题根因
  • 执行顺序逻辑错误:Process::run()是同步阻塞方法,调用后会一直阻塞等待进程执行完成、或触发默认的60秒超时抛出异常,才会继续执行后续代码。你当前将stop(15)写在run()之后,在进程运行阶段stop()根本不会被触发,等执行到stop()时要么进程已经结束、要么已经抛出了60秒超时错误。
  • 默认超时优先级更高:Symfony Process默认启用了60秒的全局执行超时,即使你逻辑正确,如果你没有手动修改超时配置,进程运行到60秒时会直接抛出超时异常,不会等到你调用stop()。
  • 信号未传递到子进程:你使用fromShellCommandline启动进程时,实际会先启动一个bash父进程,再由bash派生receive.sh子进程。默认情况下stop()发送的终止信号只会发给bash父进程,如果父进程没有把信号传递给子进程,receive.sh会继续运行,导致Process组件认为进程还未终止。
修复方案

1. 调整执行逻辑,改用异步启动

如果你需要主动控制进程的终止时机,不要用同步的run(),改用异步start()方法,自定义等待时长后调用stop(),同时关闭默认的60秒超时:

$process = Process::fromShellCommandline('bash ./receive.sh \
    url=' . env('SGW_URL') . ' \
    cert=certs/privateKey.p12?' . env('SGW_CERT_PASS'),
        '/var/www/sgwClientFiles/');

// 关闭默认60秒超时,也可设置为你预期的最大超时时间,比如75秒
$process->setTimeout(null);

// 异步启动进程,不会阻塞
$process->start();

// 等待15秒
sleep(15);

// 终止进程,第二个参数可指定先发送SIGTERM,超时未终止再发SIGKILL
$process->stop(10, SIGTERM);

if (!$process->isSuccessful()) {
    throw new ProcessFailedException($process);
}

return $process;

2. 解决子进程信号传递问题

如果调整后还是出现进程无法终止的情况,可以修改启动命令,用exec替换bash进程,让receive.sh直接成为主进程,信号可以直接发到脚本进程:

// 把bash换成exec bash,让receive.sh接管进程ID
$process = Process::fromShellCommandline('exec bash ./receive.sh \
    url=' . env('SGW_URL') . ' \
    cert=certs/privateKey.p12?' . env('SGW_CERT_PASS'),
        '/var/www/sgwClientFiles/');

如果脚本本身忽略SIGTERM信号,可以在调用stop()时指定直接发送SIGKILL强制终止,或者给脚本添加信号处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 02:09:02