Home | History | Annotate | Line # | Download | only in dist
      1  1.1  christos #!/bin/sh
      2  1.1  christos #
      3  1.1  christos # procsystime - print process system call time details.
      4  1.1  christos #               Written using DTrace (Solaris 10 3/05).
      5  1.1  christos #
      6  1.1  christos # $Id: procsystime,v 1.1.1.1 2015/09/30 22:01:06 christos Exp $
      7  1.1  christos #
      8  1.1  christos # USAGE:	procsystime [-acehoT] [ -p PID | -n name | command ]
      9  1.1  christos #
     10  1.1  christos #		-p PID          # examine this PID
     11  1.1  christos #		-n name         # examine this process name
     12  1.1  christos #		-a              # print all details
     13  1.1  christos #		-c              # print syscall counts
     14  1.1  christos #		-e              # print elapsed times
     15  1.1  christos #		-o              # print CPU times
     16  1.1  christos #		-T              # print totals
     17  1.1  christos #         eg,
     18  1.1  christos #		procsystime -p 1871     # examine PID 1871
     19  1.1  christos #		procsystime -n tar      # examine processes called "tar"
     20  1.1  christos #		procsystime -aTn bash   # print all details for bash shells
     21  1.1  christos #		procsystime df -h       # run and examine "df -h"
     22  1.1  christos #
     23  1.1  christos # The elapsed times are interesting, to help identify syscalls that take
     24  1.1  christos # some time to complete (during which the process may have slept). CPU time
     25  1.1  christos # helps us identify syscalls that are consuming CPU cycles to run.
     26  1.1  christos #
     27  1.1  christos # FIELDS:
     28  1.1  christos #		SYSCALL         System call name
     29  1.1  christos #		TIME (ns)       Total time, nanoseconds
     30  1.1  christos #		COUNT           Number of occurrences
     31  1.1  christos #
     32  1.1  christos # COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
     33  1.1  christos #
     34  1.1  christos # CDDL HEADER START
     35  1.1  christos #
     36  1.1  christos #  The contents of this file are subject to the terms of the
     37  1.1  christos #  Common Development and Distribution License, Version 1.0 only
     38  1.1  christos #  (the "License").  You may not use this file except in compliance
     39  1.1  christos #  with the License.
     40  1.1  christos #
     41  1.1  christos #  You can obtain a copy of the license at Docs/cddl1.txt
     42  1.1  christos #  or http://www.opensolaris.org/os/licensing.
     43  1.1  christos #  See the License for the specific language governing permissions
     44  1.1  christos #  and limitations under the License.
     45  1.1  christos #
     46  1.1  christos # CDDL HEADER END
     47  1.1  christos #
     48  1.1  christos # Author: Brendan Gregg  [Sydney, Australia]
     49  1.1  christos #
     50  1.1  christos # 27-Apr-2005   Brendan Gregg   Created this.
     51  1.1  christos # 08-Jun-2005	   "      "	Added command option.
     52  1.1  christos # 22-Sep-2005	   "      "	Allowed systemwide tracing.
     53  1.1  christos # 22-Sep-2005	   "      "	Last update.
     54  1.1  christos #
     55  1.1  christos 
     56  1.1  christos 
     57  1.1  christos ##############################
     58  1.1  christos # --- Process Arguments ---
     59  1.1  christos #
     60  1.1  christos 
     61  1.1  christos ### Default variables
     62  1.1  christos opt_filter=0; opt_pid=0; opt_name=0; pid=0; pname=".";
     63  1.1  christos opt_elapsed=0; opt_cpu=0; opt_counts=0; opt_totals=0
     64  1.1  christos opt_command=0; command="";
     65  1.1  christos 
     66  1.1  christos ### Process options
     67  1.1  christos while getopts acehn:op:T name
     68  1.1  christos do
     69  1.1  christos         case $name in
     70  1.1  christos         p)      opt_filter=1; opt_pid=1; pid=$OPTARG ;;
     71  1.1  christos         n)      opt_filter=1; opt_name=1; pname=$OPTARG ;;
     72  1.1  christos 	a)	opt_totals=1; opt_elapsed=1; opt_cpu=1; opt_counts=1 ;;
     73  1.1  christos 	e)	opt_elapsed=1 ;;
     74  1.1  christos 	c)	opt_counts=1 ;;
     75  1.1  christos 	o)	opt_cpu=1 ;;
     76  1.1  christos 	T)	opt_totals=1 ;;
     77  1.1  christos         h|?)    cat <<-END >&2
     78  1.1  christos 		USAGE: procsystime [-aceho] [ -p PID | -n name | command ]
     79  1.1  christos 		                  -p PID          # examine this PID
     80  1.1  christos 		                  -n name         # examine this process name
     81  1.1  christos 		                  -a              # print all details
     82  1.1  christos 		                  -e              # print elapsed times
     83  1.1  christos 		                  -c              # print syscall counts
     84  1.1  christos 		                  -o              # print CPU times
     85  1.1  christos 		                  -T              # print totals
     86  1.1  christos 		  eg,
     87  1.1  christos 		       procsystime -p 1871     # examine PID 1871
     88  1.1  christos 		       procsystime -n tar      # examine processes called "tar"
     89  1.1  christos 		       procsystime -aTn bash   # print all details for bash
     90  1.1  christos 		       procsystime df -h       # run and examine "df -h"
     91  1.1  christos 		END
     92  1.1  christos 		exit 1
     93  1.1  christos         esac
     94  1.1  christos done
     95  1.1  christos shift `expr $OPTIND - 1`
     96  1.1  christos 
     97  1.1  christos ### Option logic
     98  1.1  christos if [ $opt_pid -eq 0 -a $opt_name -eq 0 -a "$*" != "" ]; then
     99  1.1  christos 	opt_filter=1
    100  1.1  christos 	opt_command=1
    101  1.1  christos 	command="$*"
    102  1.1  christos fi
    103  1.1  christos if [ $opt_elapsed -eq 0 -a $opt_cpu -eq 0 -a $opt_counts -eq 0 ]; then
    104  1.1  christos 	opt_elapsed=1;
    105  1.1  christos fi
    106  1.1  christos 
    107  1.1  christos 
    108  1.1  christos #################################
    109  1.1  christos # --- Main Program, DTrace ---
    110  1.1  christos #
    111  1.1  christos dtrace='
    112  1.1  christos  #pragma D option quiet
    113  1.1  christos 
    114  1.1  christos  /*
    115  1.1  christos   * Command line arguments
    116  1.1  christos   */
    117  1.1  christos  inline int OPT_elapsed  = '$opt_elapsed';
    118  1.1  christos  inline int OPT_cpu      = '$opt_cpu';
    119  1.1  christos  inline int OPT_counts   = '$opt_counts';
    120  1.1  christos  inline int OPT_filter   = '$opt_filter';
    121  1.1  christos  inline int OPT_pid      = '$opt_pid';
    122  1.1  christos  inline int OPT_name     = '$opt_name';
    123  1.1  christos  inline int OPT_totals   = '$opt_totals';
    124  1.1  christos  inline int OPT_command  = '$opt_command';
    125  1.1  christos  inline int PID          = '$pid';
    126  1.1  christos  inline string NAME      = "'$pname'";
    127  1.1  christos  inline string COMMAND   = "'$command'";
    128  1.1  christos 
    129  1.1  christos  dtrace:::BEGIN 
    130  1.1  christos  {
    131  1.1  christos 	self->start = 0;
    132  1.1  christos 	self->vstart = 0;
    133  1.1  christos  }
    134  1.1  christos  dtrace:::BEGIN 
    135  1.1  christos  /! OPT_command/
    136  1.1  christos  {
    137  1.1  christos 	printf("Tracing... Hit Ctrl-C to end...\n");
    138  1.1  christos  }
    139  1.1  christos 
    140  1.1  christos  /*
    141  1.1  christos   * Set start timestamp and counts
    142  1.1  christos   */
    143  1.1  christos  syscall:::entry
    144  1.1  christos  /(! OPT_filter) ||
    145  1.1  christos   (OPT_pid && pid == PID) ||
    146  1.1  christos   (OPT_name && execname == NAME) ||
    147  1.1  christos   (OPT_command && pid == $target)/
    148  1.1  christos  {
    149  1.1  christos 	self->ok = 1;
    150  1.1  christos  }
    151  1.1  christos  syscall:::entry
    152  1.1  christos  /self->ok/
    153  1.1  christos  {
    154  1.1  christos 	OPT_counts ? @Counts[probefunc] = count() : 1;
    155  1.1  christos 	(OPT_counts && OPT_totals) ? @Counts["TOTAL:"] = count() : 1;
    156  1.1  christos 	OPT_elapsed ? self->start = timestamp : 1;
    157  1.1  christos 	OPT_cpu ? self->vstart = vtimestamp : 1;
    158  1.1  christos 	self->ok = 0;
    159  1.1  christos  }
    160  1.1  christos 
    161  1.1  christos  /*
    162  1.1  christos   * Calculate time deltas
    163  1.1  christos   */
    164  1.1  christos  syscall:::return
    165  1.1  christos  /self->start/
    166  1.1  christos  {
    167  1.1  christos 	this->elapsed = timestamp - self->start;
    168  1.1  christos 	@Elapsed[probefunc] = sum(this->elapsed);
    169  1.1  christos 	OPT_totals ? @Elapsed["TOTAL:"] = sum(this->elapsed) : 1;
    170  1.1  christos 	self->start = 0;
    171  1.1  christos  }
    172  1.1  christos  syscall:::return
    173  1.1  christos  /self->vstart/
    174  1.1  christos  {
    175  1.1  christos 	this->cpu = vtimestamp - self->vstart;
    176  1.1  christos 	@CPU[probefunc] = sum(this->cpu);
    177  1.1  christos 	OPT_totals ? @CPU["TOTAL:"] = sum(this->cpu) : 1;
    178  1.1  christos 	self->vstart = 0;
    179  1.1  christos  }
    180  1.1  christos 
    181  1.1  christos  /*
    182  1.1  christos   * Elapsed time report
    183  1.1  christos   */
    184  1.1  christos  dtrace:::END 
    185  1.1  christos  /OPT_elapsed/
    186  1.1  christos  {
    187  1.1  christos 	printf("\nElapsed Times for ");
    188  1.1  christos 	OPT_pid ? printf("PID %d,\n\n",PID) : 1;
    189  1.1  christos 	OPT_name ? printf("processes %s,\n\n",NAME) : 1;
    190  1.1  christos 	OPT_command ? printf("command %s,\n\n",COMMAND) : 1;
    191  1.1  christos 	(! OPT_filter) ? printf("all processes,\n\n") : 1;
    192  1.1  christos 	printf("%16s %18s\n","SYSCALL","TIME (ns)");
    193  1.1  christos 	printa("%16s %@18d\n",@Elapsed);
    194  1.1  christos  }
    195  1.1  christos 
    196  1.1  christos  /*
    197  1.1  christos   * CPU time report
    198  1.1  christos   */
    199  1.1  christos  dtrace:::END 
    200  1.1  christos  /OPT_cpu/
    201  1.1  christos  {
    202  1.1  christos 	printf("\nCPU Times for ");
    203  1.1  christos 	OPT_pid ? printf("PID %d,\n\n",PID) : 1;
    204  1.1  christos 	OPT_name ? printf("processes %s,\n\n",NAME) : 1;
    205  1.1  christos 	OPT_command ? printf("command %s,\n\n",COMMAND) : 1;
    206  1.1  christos 	(! OPT_filter) ? printf("all processes,\n\n") : 1;
    207  1.1  christos 	printf("%16s %18s\n","SYSCALL","TIME (ns)");
    208  1.1  christos 	printa("%16s %@18d\n",@CPU);
    209  1.1  christos  }
    210  1.1  christos 
    211  1.1  christos  /*
    212  1.1  christos   * Syscall count report
    213  1.1  christos   */
    214  1.1  christos  dtrace:::END 
    215  1.1  christos  /OPT_counts/
    216  1.1  christos  {
    217  1.1  christos 	printf("\nSyscall Counts for ");
    218  1.1  christos 	OPT_pid ? printf("PID %d,\n\n",PID) : 1;
    219  1.1  christos 	OPT_name ? printf("processes %s,\n\n",NAME) : 1;
    220  1.1  christos 	OPT_command ? printf("command %s,\n\n",COMMAND) : 1;
    221  1.1  christos 	(! OPT_filter) ? printf("all processes,\n\n") : 1;
    222  1.1  christos 	printf("%16s %18s\n","SYSCALL","COUNT");
    223  1.1  christos 	OPT_counts ? printa("%16s %@18d\n",@Counts) : 1;
    224  1.1  christos  }
    225  1.1  christos '
    226  1.1  christos 
    227  1.1  christos ### Run DTrace
    228  1.1  christos if [ $opt_command -eq 1 ]; then
    229  1.1  christos 	/usr/sbin/dtrace -n "$dtrace" -x evaltime=exec -c "$command" >&2
    230  1.1  christos else
    231  1.1  christos 	/usr/sbin/dtrace -n "$dtrace" >&2
    232  1.1  christos fi
    233  1.1  christos 
    234