1: #!/bin/ksh 2: # 3: ## sh code translated to ksh, with some additional optimizations 4: ## RB Oct 2002 5: #--------------------------------------------------------------- 6: 7: # 8: # Copyright 1995, by Hewlett-Packard Company 9: # 10: # The code in this file is from the book "Shell Programming 11: # Examples" by Bruce Blinn, published by Prentice Hall. 12: # This file may be copied free of charge for personal, 13: # non-commercial use provided that this notice appears in 14: # all copies of the file. There is no warranty, either 15: # expressed or implied, supplied with this code. 16: # 17: # NAME 18: # ptree - print a process tree 19: # 20: # SYNOPSIS 21: # ptree [-n] [pid] 22: # ptree [-n] [pid] [level] [datafile] 23: # 24: # DESCRIPTION 25: # This command will print the process tree for the 26: # process identified by pid. When called by the user, 27: # only the first format shown should be used. If the 28: # process ID (pid) is not passed, process 1 is assumed. 29: # 30: # The second format of this command is only used when 31: # this command calls itself recursively to print the next 32: # level of the process tree. 33: # 34: # -n Do not recurse 35: # 36: # RETURN VALUE 37: # 0 Successful completion 38: # 1 Usage error 39: # 40: ############################################################ 41: ## Put our own directory in the PATH, since we use recursion 42: ## ksh lets us avoid using `dirname` 43: ## Also, make sure /usr/bin/ps is ahead of any other version of ps (/usr/ucb etc.) 44: PATH=/usr/bin:$PATH:${0%/*} 45: 46: ## Don't even import this function if we've already used it 47: if [[ -z "$SYSTEM" ]]; then 48: . SystemType.sh 49: fi 50: 51: integer INDENT LEVEL 52: 53: CMDNAME=${0##*/} 54: USAGE="Usage: $CMDNAME [-n] [pid]" 55: RECURSIVE=TRUE # List processes recursively 56: PROCESS= # PID of the starting process 57: LEVEL= # Indentation level (num parents) 58: DATAFILE= # Reformatted output from ps 59: PS_OPTS= # Options for the ps command 60: OLD_IFS=$IFS # Original value of IFS variable 61: 62: ## Setting SYSTEM is expensive - don't do it more than once 63: SYSTEM=${SYSTEM:=`SystemType`}; export SYSTEM 64: # SYSTEM=`SystemType` # String identifying the system 65: 66: # 67: # Temporaries 68: # 69: PID= # Process ID 70: PPID= # Process ID of the parent process 71: OWNER= # Owner of the process 72: NAME= # Name of the process 73: LINE= # Line from the data file 74: OUTLINE= # Line of output 75: INDENT= # Column number where line begins 76: 77: trap 'rm -f /tmp/*.$$; exit 1' 1 2 3 15 78: 79: FillLine() { 80: # 81: # SYNOPSIS 82: # FillLine line column 83: # 84: integer _COLUMN _LEN 85: _LINE="$1" 86: _COLUMN=$2 87: ## Using ksh lets us do this arithmetic internally 88: ## otherwise `expr` is needed potentially thousands of times 89: _LEN=${#_LINE} 90: while [[ $_LEN -lt $_COLUMN ]] 91: do 92: _LINE="$_LINE " 93: _COLUMN=$(($_COLUMN - 1)) 94: done 95: 96: print "$_LINE" 97: } 98: 99: while : 100: do 101: case $1 in 102: -n) RECURSIVE=FALSE 103: shift 104: ;; 105: --) shift 106: break 107: ;; 108: -*) print "$USAGE" 1>&2 109: exit 1 110: ;; 111: *) break 112: ;; 113: esac 114: done 115: 116: # 117: # Make sure the number of parameters is reasonable. 118: # 119: if [[ $# -eq 0 ]] then 120: PROCESS=1 121: LEVEL=0 122: DATAFILE=/tmp/ptree.$$ 123: elif [[ $# -eq 1 ]]; then 124: PROCESS=$1 125: LEVEL=0 126: DATAFILE=/tmp/ptree.$$ 127: elif [[ $# -eq 3 ]]; then 128: PROCESS=$1 129: LEVEL=$2 130: DATAFILE=$3 131: else 132: print "$USAGE" 1>&2 133: exit 1 134: fi 135: 136: if [[ "$LEVEL" = 0 ]]; then 137: # 138: # Determine which options to use with the ps command. 139: # 140: case $SYSTEM in 141: SUNBSD | ULTRIX ) PS_OPTS="-auwx" ;; 142: * ) PS_OPTS="-ef" ;; 143: esac 144: 145: # 146: # Build the data file. 147: # 148: rm -f $DATAFILE 149: 150: ## Fragile programming! - depends closely on the exact output of ps 151: case $SYSTEM in 152: SGI62 ) COL=47 ;; 153: AIX | HP | SGI | SOLARIS ) COL=48 ;; 154: SUNBSD | DECOSF | SGI65 ) COL=57 ;; 155: ULTRIX ) COL=51 ;; 156: * ) print "Unexpected system type." 1>&2 157: exit 1 ;; 158: esac 159: 160: ## Original code used a scratch file and loop to generate $DATAFILE 161: ## Replaced by piping through awk. 162: ps $PS_OPTS | sed '1d' | sort | awk '{print $2,$3,$1,substr($0,'$COL')}' > $DATAFILE 163: fi 164: 165: # 166: # Print the current process. 167: # 168: ## Use internal arithmetic again, instead of calling 'expr' 169: INDENT=$(( $LEVEL * 2 )) 170: OUTLINE=`FillLine "" $INDENT` 171: 172: LINE=`grep "^$PROCESS " $DATAFILE` 173: set $LINE 174: OUTLINE="$OUTLINE $1" 175: OUTLINE=`FillLine "$OUTLINE" 30` 176: OUTLINE="$OUTLINE $3 $4" 177: print "$OUTLINE" 178: 179: if [[ "$RECURSIVE" = "TRUE" ]];then 180: LEVEL=$(($LEVEL + 1)) 181: while read LINE 182: do 183: set $LINE 184: # 185: # For every process that is a child of the 186: # current process, invoke this command ($0) 187: # recursively. 188: # 189: if [[ "$2" = "$PROCESS" ]]; then 190: $0 $1 $LEVEL $DATAFILE 191: fi 192: done <$DATAFILE 193: fi 194: 195: rm -f /tmp/*.$$ 196: exit 0
last modified 22/03/2012 | Introduction | Table of Contents (frame/no frame) |
Printable (single file) |
© Dartmouth College |