Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!


Click here to return to the 'missing ptree' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
missing ptree
Authored by: mzs on Apr 28, '06 02:12:40PM
Your hint reminded me that I missed ptree whenever I was not using Solaris. I use Solaris, FreeBSD, Darwin, and Linux. On Linux I have pstree which is a lot like ptree on Solaris but I use so many different machines that it is not practical for me to compile pstree on all of them. Hence I wrote a little shell script ptree that I use instead. It is usually mounted somewhere and if not I can easily get it onto the new machine:

ptree:


#!/bin/sh

dirname=`/usr/bin/dirname "$0"` || exit

sed=/usr/bin/sed

sys=`/usr/bin/uname -s` || sys=`/bin/uname -s` || exit
case "$sys" in
    SunOS)
	pspre='/bin/ps -o pid,ppid'
	pssuf='-o comm'
	user=-e	# the e option takes precedence over u
	with=1	# don't show sched, init, pageout, and fsflush
	;;
    Linux)	# a lot like Solaris
	pspre='/bin/ps -o pid,ppid'
	pssuf='-o comm'
	user=-e	# the e option takes precedence over u
	with=0
	sed=/bin/sed
	;;
    *)	# Darwin, FreeBSD, etc
	pspre='/bin/ps -o pid,ppid -ax'
	pssuf='-o command'
	user=''
	with=0
esac

case $# in
    0)	# no args, just run with the defaults
	;;
    *)
	case "$1" in
	    -*)	# an argument for ps, pass it on
		;;
	    [0123456789]*)
		# pid to include in the tree
		with="$1"
		shift
		;;
	    *)	# otherwise a username
		case "$sys" in
		    SunOS | Linux)
			uid=`/usr/bin/id | \
			    /usr/bin/awk -F= 'BEGIN { RS=" " }
				/^[Uu][Ii][Dd]=/ { print $2 }' | \
			    "$sed" 's/[^0-9].*//'`
			user="-u $uid"
			;;
		    *)	# Darwin, FreeBSD, etc
			user="-U $1"
			;;
		esac

		shift
		;;
	esac
	;;
esac


$pspre $user "$@" $pssuf | \
    "$dirname"/otree id="PID" pid="PPID" infon=3 with="$with" headn=1
It uses otree to do its work. This is a generally useful awk script for displaying tree-like output. Put otree in the same directory where you put the ptree script.

otree:


#!/usr/bin/awk -f
# headn : if set to 1, then the first record is a header
# id, pid, info : strings in the header matching id, parent id, and info
# idn, pidn, infon : parameter numbers otherwise
# with : an id to include in the tree
NR == headn {
	j=3

	if (idn) j--
	if (pidn) j--
	if (infon) j--

	for (i=1; i <= NF; i++) {
		if (!idn && $i == id) {
			idn=i

			if (j-- == 1) next;
		} else if (!pidn && $i == pid) {
			pidn=i

			if (j-- == 1) next;
		} else if (!infon && $i == info) {
			infon=i

			if (j-- == 1) next;
		}
	}
}

{
	# save parent id
	pida[$idn]=$pidn

	# add to the list children for the parent id
	if (cidan[$pidn]) {
		cidan[$pidn]++
		cida[$pidn]=cida[$pidn] $idn " "
	} else {
		cidan[$pidn]=1
		cida[$pidn]=$idn " "
	}

	# This block finds the beginning of the info string
	j=0
	last=0
	n=length($0)
	for (i=1; i <= n; i++) {
		a=substr($0, i, 1)

		# last is 0 for FS, 1 otherwise
		if (split(a, b) == last)
			continue

		if (last) {
			last=0
			continue
		} else {
			last=1
		}

		if (++j >= infon)
			break
	}

	# tuck away all of the info string
	infoa[$idn]=substr($0, i)

	# tuck away the id in an orderred list starting from 1
	ida[NR]=$idn
}

END {
	# find the root of the tree containing with
	i=with
	while (j=pida[i]) {
		cida[j]=i " "
		i=j
	}

	# There may be no children of i, we need to create a stack
	# thath includes all roots then.
	stack[0]=cida[i]
	if (!stack[0]) {
		stack[0]=""
		for (i=2; i <= NR; i++) {
			j=ida[i]

			j=pida[j]
			if (pida[j])
				continue

			if (seen[j])
				continue

			seen[j]=1
			stack[0]=stack[0] j " "
		}
	}

	# Real awk does not allow us to define functions, so we use
	# arrays of lists as a stack instead of recursive functions.
	j=0
	while (j != -1) {
		i=index(stack[j], " ")
		if (i >= 1) {
			id=substr(stack[j], 1, i - 1)
			stack[j]=substr(stack[j], i + 1)

			for (i=0; i < j; i++)
				printf("  ")

			print id, infoa[id]

			if (cidan[id]) {
				j++
				stack[j]=cida[id]
			}
		} else {
			j--
		}
	}
}
I like my little ptree script so much that I use it even on Solaris. This is mainly because anywhere I can tack on the -o user option and get the username listed as well. Here are some ways to call it:

ptree (all processes)
ptree mzs (all of my processes)
ptree $$ -o user (all processes forward and backward from my shell, also printing the username)
You can tack on whatever options you like, most work fine. For example on Darwin and BSD I use -c or -www often.

[ Reply to This | # ]