Reputation: 31
I am new at programming. As I know is every process can create a child process. When you open a terminal, a process is created, and when you call a command inside the terminal a child process is created. I want to see that child processes and understand how it works. My friend shared his code with me but It is too complicated for me. I want to make it more simple. I hope someone can help me. Have a nice day to everyone! Here is the code:
#!/bin/bash
#Function that will display the process with the parent process ID given as argument
function get_child()
{
#depth will hold the number of generation. E.g 0 for main process, 1 for children, 2 for grandchildre and so on
local depth=$depth
# ps --ppid $parent will get the processes whose parent ID is $parent
output=`ps --ppid $parent`
#increment the depth
depth=$(($depth+1))
# Pipe the value of $output to tail -n + 2. It will remove the first line from $output because that line only contains title of the columns
# awk '{print $1}' will only print the first column (Process ID) of eachline
# While read child will iterate over all the process IDs referred as $child
echo "$output" | tail -n +2 | awk '{print $1}' | while read child
do
#If $child is not empty i.e. it contains a process ID then echo the child process id and send that process id as parent process id to the get_child() function recursively
if [ $child ]
then
for((i=0;i<depth;i++))
do
echo -n "-"
done
echo $depth. $child
parent=$child
get_child $child $depth
fi
done
}
parent=$1
depth=0
echo $parent
get_child $parent $depth
Upvotes: 3
Views: 258
Reputation: 50750
Invoking ps
multiple times would yield inaccurate results as new processes may be created and the old ones may terminate between invocations.
Taking a single snapshot and drawing the process tree based on that sure is a better approach; it would produce an accurate result at least for an instant.
The function below does that. Awk is for portability (not all ps
implementations have --ppid
).
ptree() {
ps -A -o pid= -o ppid= |
awk -v pid="${1:-1}" '
function ptree(ppid, arm, i) {
print arm ppid
sub(/ ?$/, "- ", arm)
for (i=1; i<=count[ppid]; ++i)
ptree(pids[ppid,i], arm)
}
{
pids[$2,++count[$2]] = $1
ppids[$2]
}
END {
if (pid in ppids)
ptree(pid)
}'
}
Upvotes: 1
Reputation: 19555
A short version of your algorithm.
I intentionally leave it without comment, so you can do the research on the Bash features and syntax, and gain some knowledge on your own for your assignment.
#!/usr/bin/env bash
get_child()
{
local -i pid=0 ppid=$1 depth=$2
printf '%*s%d. %d\n' "$depth" '' "$depth" "$ppid"
while read -r pid; do
((pid)) && get_child $pid $((depth + 1))
done < <(ps -o pid= --ppid $ppid)
}
get_child $1 0
No Bashism version:
#!/usr/bin/env sh
get_child()
{
p=0
printf '%*s%d. %d\n' $2 '' $2 $1
ps -o pid= --ppid $1 |
while read -r p; do
[ $p -ne 0 ] && get_child $p $(($2 + 1))
done
}
get_child $1 0
Upvotes: 3