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

Ubuntu下Python通过subprocess启动Jar后脚本卡顿、进程无法杀死

问题原因

  1. 错误使用shell后台符&:subprocess模块默认shell=False,参数列表里的&会被当作java命令的普通参数传递,不会被解析为后台运行指令。java命令收到无效参数后要么抛出异常卡住,要么进入等待状态,导致Popen调用直接挂住,后续代码无法执行。
  2. IO重定向不完整:你仅重定向了stdout到空设备,没有处理stdin和stderr。如果jar进程需要读取标准输入(比如确认用户许可)、或者向stderr输出错误日志写满缓冲区,都会导致进程阻塞,连带父脚本卡住。
  3. 上层调用逻辑错误:上层脚本使用subprocess.run调用当前脚本时也添加了&,同样存在参数解析错误的问题,且subprocess.run本身是同步等待子进程执行完成才返回的,根本无法达到后台运行的效果。

修复方案

1. 修改当前脚本的java进程启动代码

将原Popen调用

p2 = subprocess.Popen(["java", "-jar", "serverstarter-2.0.1.jar", "&"], stdout=subprocess.DEVNULL)

替换为:

p2 = subprocess.Popen(
    ["java", "-jar", "serverstarter-2.0.1.jar"],
    stdout=subprocess.DEVNULL,
    stderr=subprocess.DEVNULL,
    stdin=subprocess.DEVNULL
)

说明:去掉无效的&参数,全量重定向三个标准IO流,避免IO阻塞导致的卡顿。如果需要排查jar本身的运行问题,可以临时将stderr改为输出到本地日志文件。

2. 修改上层调用脚本的逻辑

将原调用代码

subprocess.run(["python3", p, "&"], stdout=subprocess.DEVNULL)

替换为:

subprocess.Popen(
    ["python3", p],
    stdout=subprocess.DEVNULL,
    stderr=subprocess.DEVNULL,
    stdin=subprocess.DEVNULL
)

说明:subprocess.Popen会直接返回,让子脚本后台运行,符合你的预期需求,不需要额外加&。

可选优化(杀进程更彻底)

如果出现p2.kill()无法完全杀死java衍生的子进程的情况,可以在创建Popen时添加start_new_session=True参数,后续杀进程时调用os.killpg(os.getpgid(p2.pid), signal.SIGTERM)杀死整个进程组即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:36:04