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

启用Job Control时子shell后台进程组行为疑问咨询

Bash脚本进程组与Job Control行为解析

先看你编写的测试脚本:

#!/bin/bash

set -e
set -m
(
    echo "waiting to be killed..."
    sleep inf
)  &
bg_pid=$!
echo $bg_pid
sleep 5

echo "kill $bg_pid"
kill -- "-$bg_pid"

set -m用于启用Job Control,按预期逻辑,启用后子shell会进入独立进程组——如果不启用该选项,执行kill -- "-$bg_pid"会提示No such process,因为子shell与父shell同属一个进程组。

但实际运行脚本时,在执行kill前打印的进程层级如下:

PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
 173828  173890  173890  173890 pts/6     206742 Ss    1000   0:00 -bash
 173890  206740  206740  173890 pts/6     206742 S     1000   0:00  \_ /bin/bash ./test1.sh
 206740  206741  206741  173890 pts/6     206742 S     1000   0:00      \_ /bin/bash ./test1.s
 206741  206743  206741  173890 pts/6     206742 S     1000   0:00      |   \_ sleep inf
 206740  206742  206742  173890 pts/6     206742 S+    1000   0:00      \_ sleep 5

可以看到sleep inf(PID 206743)和它的父进程(子shell PID 206741)同属进程组206741,背后的原因可以从以下几点分析:

核心原因拆解

  • 子shell已获得独立进程组,但内部前台命令不会新建进程组
    启用set -m后,父shell确实为后台运行的子shell(PID 206741)分配了独立进程组(PGID=206741),这部分符合预期。而子shell里执行的sleep inf是它的前台作业——bash的默认逻辑是:对于子shell内的单个前台命令,不会为其单独创建新进程组,除非子shell内将命令放到后台运行。

  • 子shell继承Job Control状态,但无需拆分进程组
    子shell会继承父shell的set -m设置,但只有当子shell内部存在后台作业(比如写成sleep inf &)时,才会触发新进程组的创建。当前场景下子shell仅运行一个前台sleep命令,自然和子shell同属一个进程组。

  • kill -- "-$bg_pid"的实际作用
    这里的-$bg_pid是向进程组206741发送信号,因此即使sleep inf和子shell同属一个进程组,该kill命令依然能同时终止子shell和sleep inf进程,因为二者都在目标进程组内。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:33:23