为什么 Bash 处理子进程与 Sh 不同
Why is Bash handling child processes different compared to Sh
在Docker中使用的tini init-process提到进程组杀戮默认不激活并给出了以下示例:
docker run krallin/ubuntu-tini sh -c 'sleep 10'
如果我运行这个,然后马上按Ctrl-C,我确实要等10秒直到子进程退出。
但是,如果我使用 bash
:
而不是 sh
docker run krallin/ubuntu-tini bash -c 'sleep 10'
然后按Ctrl-C,进程立即退出。
为什么 sh
(符号链接到 dash
)和 bash
对此子进程的行为不同?
还有Bash怎么杀掉子进程,我还以为Bash默认不传播信号呢?
感谢 chepner 和 Charles Duffy 的回答:
bash -c
有一个隐式优化,如果可能的话,它使用 exec
来替换自己。 sh
(dash
) 没有这个优化。另见 this observation。
验证:
- 进程树使用
bash
:
❯ docker run --name test --rm --detach krallin/ubuntu-tini bash -c 'sleep 60'
03194d48a4dcc8225251fe1e5de2dcbb901c8a9cfd0853ae910bfe4d3735608d
❯ docker exec test ps axfo pid,ppid,args
PID PPID COMMAND
1 0 /usr/bin/tini -- bash -c sleep 60
7 1 sleep 60
- 进程树使用
sh
:
❯ docker run --name test --rm --detach krallin/ubuntu-tini sh -c 'sleep 60'
e56f207509df4b0b57f8e6b2b2760835f6784a147b200d798dffad112bb11d6a
❯ docker exec test ps axfo pid,ppid,args
PID PPID COMMAND
1 0 /usr/bin/tini -- sh -c sleep 60
7 1 sh -c sleep 60
8 7 \_ sleep 60
在Docker中使用的tini init-process提到进程组杀戮默认不激活并给出了以下示例:
docker run krallin/ubuntu-tini sh -c 'sleep 10'
如果我运行这个,然后马上按Ctrl-C,我确实要等10秒直到子进程退出。
但是,如果我使用 bash
:
sh
docker run krallin/ubuntu-tini bash -c 'sleep 10'
然后按Ctrl-C,进程立即退出。
为什么 sh
(符号链接到 dash
)和 bash
对此子进程的行为不同?
还有Bash怎么杀掉子进程,我还以为Bash默认不传播信号呢?
感谢 chepner 和 Charles Duffy 的回答:
bash -c
有一个隐式优化,如果可能的话,它使用 exec
来替换自己。 sh
(dash
) 没有这个优化。另见 this observation。
验证:
- 进程树使用
bash
:
❯ docker run --name test --rm --detach krallin/ubuntu-tini bash -c 'sleep 60'
03194d48a4dcc8225251fe1e5de2dcbb901c8a9cfd0853ae910bfe4d3735608d
❯ docker exec test ps axfo pid,ppid,args
PID PPID COMMAND
1 0 /usr/bin/tini -- bash -c sleep 60
7 1 sleep 60
- 进程树使用
sh
:
❯ docker run --name test --rm --detach krallin/ubuntu-tini sh -c 'sleep 60'
e56f207509df4b0b57f8e6b2b2760835f6784a147b200d798dffad112bb11d6a
❯ docker exec test ps axfo pid,ppid,args
PID PPID COMMAND
1 0 /usr/bin/tini -- sh -c sleep 60
7 1 sh -c sleep 60
8 7 \_ sleep 60