bash环境下直接执行ps|wc -l与赋值给变量执行的输出差异及成因
两种命令执行结果差异的核心原因
无参数执行
ps时,默认统计范围是所有和当前调用进程挂载在同一控制终端(tty)下的活动进程,不会遍历全系统进程;只要在ps扫描进程链表的瞬间,进程处于和当前tty关联的存在状态,就会被纳入统计、输出对应行。
两种场景的进程构成拆解
- 场景1:直接执行
ps | wc -l(返回结果4)
这个管道是当前交互bash直接创建的,没有中间嵌套层:- 输出第一行是ps自带的表头行,属于固定存在的内容
- 剩下3行对应扫描瞬间的3个tty关联进程:交互bash本身、管道左侧的
ps进程、管道右侧的wc进程
管道执行完成后,bash直接回收两个子进程,全程没有额外的中间进程存在。
- 场景2:通过命令替换赋值后输出,也就是执行
n=$(ps|wc -l)、echo $n(返回结果5)
bash处理命令替换的执行流程,天然会多出一个暂时不退出的中间进程:- 交互bash识别到
$()结构,首先fork出一个独立的子shell进程——这就是承载命令替换执行的容器,这个子shell和交互bash共享同一个tty - 子shell必须等待内部的
ps|wc -l管道执行完成、回收管道两端的ps、wc进程,才会把捕获的输出返回给交互bash、完成变量赋值 - 当ps启动扫描tty下的进程时,这个负责承接命令替换的子shell还处于存活等待的状态,因此会被ps纳入输出列表
对应输出的5行构成:1行表头 + 4个tty关联进程(交互bash、命令替换对应的子shell、ps进程、wc进程),比直接执行的场景刚好多1行。
- 交互bash识别到
核心逻辑说明
你之前判断命令替换会创建额外子进程,这个方向是对的。这个额外进程之所以会被ps统计到,是两个条件叠加的结果:
- 这个子shell和交互bash共享同一个tty,完全属于无参数ps的统计边界内
- 子shell的存活周期完全覆盖了ps的扫描时间窗口——ps是在子shell的上下文内启动的,ps执行的整个过程里,子shell都没退出,自然会被列在进程列表中。
内容的提问来源于stack exchange,提问作者JulienV
相关产品推荐
相关产品推荐

