pgrep -P, but for grandchildren not just children

前端 未结 6 2217
猫巷女王i
猫巷女王i 2021-01-07 05:18

I am using:

pgrep -P $$

to get the child pids of $$. But I actually want a list of grandchildren and great grandchild too.

How do I

6条回答
  •  春和景丽
    2021-01-07 06:09

    Using nothing but bash builtins (not even ps or pgrep!):

    #!/usr/bin/env bash
    
    collect_children() {
      # format of /proc/[pid]/stat file; group 1 is PID, group 2 is its parent
      stat_re='^([[:digit:]]+) [(].*[)] [[:alpha:]] ([[:digit:]]+) '
    
      # read process tree into a bash array
      declare -g children=( )              # map each PID to a string listing its children
      for f in /proc/[[:digit:]]*/stat; do # forcing initial digit skips /proc/net/stat
        read -r line <"$f" && [[ $line =~ $stat_re ]] || continue
        children[${BASH_REMATCH[2]}]+="${BASH_REMATCH[1]} "
      done
    }
    
    # run a fresh collection, then walk the tree
    all_children_of() { collect_children; _all_children_of "$@"; }
    
    _all_children_of() {
      local -a immediate_children
      local child
      read -r -a immediate_children <<<"${children[$1]}"
      for child in "${immediate_children[@]}"; do
        echo "$child"
        _all_children_of "$child"
      done
    }
    
    all_children_of "$@"
    

    On my local system, time all_children_of 1 >/dev/null (invoking the function in an already-running shell) clocks in the neighborhood of 0.018s -- typically, 0.013s for the collect_children stage (the one-time action of reading the process tree), and 0.05s for the recursive walk of that tree triggered by the initial call of _all_children_of.

    Prior timings were testing only the time needed for the walk, discarding the time needed for the scan.

提交回复
热议问题