运行Shell脚本时,为何子Shell的PID、PPID与主Shell一致?
问题解析
你的疑惑来自bash的两个特性:$$参数的特殊取值规则,以及bash对子shell的进程优化。
1. $$不是子shell的真实PID
在bash脚本中,$$是一个特殊参数,它的取值是启动当前脚本的主shell进程的PID,这个值会被子shell直接继承,不会随子shell的进程变化而改变。如果想获取子shell的真实PID,需要使用bash特有的$BASHPID变量——这个变量才会返回当前bash实例(包括子shell)的真实进程ID。
2. 子shell可能没有创建新进程
bash会对仅包含内置命令(比如echo)的子shell做优化:不fork新的进程,直接在主shell进程中执行子shell的代码。这时候子shell本质上和主shell是同一个进程,所以它的真实PID和主shell完全一致,对应的父进程ID($PPID)自然也和主shell的PPID相同(也就是你例子中的143,主shell的父进程PID)。
如果在子shell中加入一个外部命令(比如ps),bash就必须创建新进程来执行,此时子shell的真实PID会和主shell不同,$PPID也会变成主shell的PID:
# 修改old.sh的子shell部分 ( echo $$ # 仍然输出主shell PID 632 echo $PPID # 此时会输出主shell PID 632 echo $BASHPID # 输出子shell的真实PID(新的数值) ps -p $BASHPID # 验证子shell的父进程 )
而你例子中bash /tmp/new.sh是启动了一个独立的bash进程,bash必须fork新进程来执行这个外部脚本,所以它的PID是新的634,PPID是主shell的PID632,这符合预期。
内容的提问来源于stack exchange,提问作者Udeshya D.
相关产品推荐
相关产品推荐

