#!/usr/bin/env perl use strict; use warnings; use constant { CHILD => 0, PARENT => 1, GRANDPARENT => 2, GREATGRANDPARENT => 3, }; my $table = [ { pid => 0, ppid => 0, cmd => 'root' }, { pid => 603, ppid => 0, cmd => 'cron_parent' }, { pid => 18421, ppid => 603, cmd => 'cron_child' }, { pid => 18423, ppid => 18421, cmd => 'sh_mon' }, { pid => 18425, ppid => 18423, cmd => 'sh_kit' }, { pid => 18444, ppid => 18425, cmd => 'java' }, { pid => 28421, ppid => 603, cmd => 'cron_child' }, { pid => 28423, ppid => 18421, cmd => 'sh_mon' }, { pid => 28425, ppid => 18423, cmd => 'sh_kit' }, { pid => 28444, ppid => 18425, cmd => 'java' }, { pid => 28445, ppid => 18425, cmd => 'java' }, { pid => 99999, ppid => 18421, cmd => 'java' }, { pid => 2, ppid => 1, cmd => 'unwanted' }, ]; my $ancestry = 3; my %tree; { my %all; for (@$table) { $all{$_->{pid}} = $_; $tree{$_->{pid}} = [ $_ ] if $_->{cmd} =~ /java/; } for my $child (keys %tree) { my $ppid = $all{$child}{ppid}; for (1 .. $ancestry) { push @{$tree{$child}}, {%{$all{$ppid}}}; $ppid = $all{$ppid}{ppid}; } } } use Data::Dump; print "*** All parents ***\n"; dd [ map { $tree{$_}[PARENT] } sort keys %tree ]; print "*** 18444 grandparent ***\n"; dd $tree{18444}[GRANDPARENT]; print "*** 18444 greatgrandparent ***\n"; dd $tree{18444}[GREATGRANDPARENT]; print "*** All ancestries ***\n"; dd \%tree;