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

Shell递归脚本无法运行:按深度优先树状打印多代子进程问题

深度优先遍历打印进程树(最多k代)

我完全懂你想要的效果——用**深度优先遍历(DFS)**的方式,把每个进程的子进程直接嵌套打印在它的下方,形成清晰的树状结构,而不是先打印完一整代再打下一代。之前的实现失败大概率是因为没处理好递归时的层级缩进,或者误用到了广度优先的逻辑。

核心思路

要实现这个需求,需要抓住两个关键点:

  1. 递归时维护当前层级和剩余可遍历深度,确保不超过k代的限制
  2. 通过动态缩进来体现进程的父子层级关系,让树状结构直观可读

示例实现(Python + psutil)

下面用Python结合psutil库(方便获取进程信息)来写一个符合要求的递归函数:

import psutil

def print_process_tree(pid, current_depth=0, max_depth=3, indent=""):
    try:
        # 获取当前进程对象
        process = psutil.Process(pid)
        # 打印当前进程,用缩进体现层级
        print(f"{indent}├─ PID: {pid} ({process.name()})")
        
        # 已经到达最大允许深度,停止递归
        if current_depth >= max_depth - 1:
            return
        
        # 只获取当前进程的直接子进程(不递归获取孙子进程)
        direct_children = process.children(recursive=False)
        
        # 遍历每个直接子进程,递归处理
        for idx, child_proc in enumerate(direct_children):
            # 调整缩进:如果是最后一个子进程,后续缩进不再显示竖线,避免树状错乱
            new_indent = indent + ("│  " if idx < len(direct_children)-1 else "   ")
            # 递归调用,层级+1,剩余深度递减
            print_process_tree(child_proc.pid, current_depth + 1, max_depth, new_indent)
    except psutil.NoSuchProcess:
        # 处理进程不存在的情况
        print(f"{indent}├─ PID: {pid} (进程不存在)")

# 调用示例:打印PID为1的进程及其最多3代子进程
print_process_tree(1, max_depth=3)

关键细节解释

  • current_depth:记录当前遍历到第几代(从0开始,代表目标进程本身是第0代)
  • max_depth:就是你需求中的k值,控制最多打印多少代
  • 缩进逻辑:通过new_indent动态调整,最后一个子进程的后续缩进用空格代替竖线,保证树状结构的视觉连贯性
  • children(recursive=False):只获取直接子进程,确保我们是深度优先遍历,而不是一次性拿到所有后代

不用psutil的替代方案(Linux系统)

如果不想用第三方库,可以通过系统命令pgrep -P <pid>来获取直接子进程,修改后的代码片段:

import subprocess

def get_direct_child_pids(pid):
    try:
        # 执行pgrep命令获取当前进程的直接子进程PID
        output = subprocess.check_output(["pgrep", "-P", str(pid)], text=True)
        return [int(pid_str.strip()) for pid_str in output.split()]
    except subprocess.CalledProcessError:
        # 没有子进程时返回空列表
        return []

# 修改print_process_tree中的子进程获取部分:
# direct_children = process.children(recursive=False)
# 替换为:
direct_child_pids = get_direct_child_pids(pid)
# 若不需要进程名称,直接遍历PID即可
for idx, child_pid in enumerate(direct_child_pids):
    new_indent = indent + ("│  " if idx < len(direct_child_pids)-1 else "   ")
    print_process_tree(child_pid, current_depth + 1, max_depth, new_indent)

这样调整后,就能完美实现你想要的深度优先树状打印效果——每个进程的子进程直接在它下方缩进显示,遍历完一个分支再处理下一个兄弟分支。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:43:32