pgrep -P, but for grandchildren not just children

前端 未结 6 2115
猫巷女王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:18

    I've already posted an attempted solution. It's short and effective, and seems in line with the OP's question, so I'll leave it as it is. However, it has some performance and portability problems that mean it's not a good general solution. This code attempts to fix the problems:

    top_pid=$1
    
    # Make a list of all process pids and their parent pids
    ps_output=$(ps -e -o pid= -o ppid=)
    
    # Populate a sparse array mapping pids to (string) lists of child pids
    children_of=()
    while read -r pid ppid ; do
        [[ -n $pid && pid -ne ppid ]] && children_of[ppid]+=" $pid"
    done <<< "$ps_output"
    
    # Add children to the list of pids until all descendants are found
    pids=( "$top_pid" )
    unproc_idx=0    # Index of first process whose children have not been added
    while (( ${#pids[@]} > unproc_idx )) ; do
        pid=${pids[unproc_idx++]}       # Get first unprocessed, and advance
        pids+=( ${children_of[pid]-} )  # Add child pids (ignore ShellCheck)
    done
    
    # Do something with the list of pids (here, just print them)
    printf '%s\n' "${pids[@]}"
    

    The basic approach of using a breadth-first search to build up the tree has been retained, but the essential information about processes is obtained with a single (POSIX-compliant) run of ps. pgrep is no longer used because it is not in POSIX and it could be run many times. Also, a very inefficient way of removing items from the queue (copy all but one element of it) has been replaced with manipulation of an index variable.

    Average (real) run time is 0.050s when run on pid 0 on my oldish Linux system with around 400 processes.

    I've only tested it on Linux, but it only uses Bash 3 features and POSIX-compliant features of ps so it should work on other systems too.

提交回复
热议问题