#!/bin/ksh # # USAGE ./template.sh [ -p pid ] [ -n name ] [ -s seconds ] # # Template to generate a big chunk of system call tracing # ############################## # --- Process Arguments --- # ### default vairables filter=0 opt_pid=0; pid=0 opt_name=0; pname=. opt_duration=0; duration=10 ### process options while getopts p:n:s: name do case $name in p) opt_pid=1; pid=$OPTARG ;; n) opt_name=1; pname=$OPTARG ;; s) opt_duration=1; duration=$OPTARG ;; h|?) cat <<-END >&2 USAGE: ./template.sh [ -p pid ] [ -n name ] [ -s seconds ] eg, template.sh -p 666 # trace pid 666 template.sh -n sshd # trace sshd processes template.sh -s 100 # trace for 100 seconds END exit 1 esac done ### option logic if (( opt_name || opt_pid )); then filter=1 fi ################################# # --- Main Program, DTrace --- # /usr/sbin/dtrace -n ' /* command line arguments */ inline int OPT_pid = '$opt_pid'; inline int OPT_name = '$opt_name'; inline int FILTER = '$filter'; inline int DURATION = '$duration'; inline int PID = '$pid'; inline string NAME = "'$pname'"; #pragma D option quiet /* constants */ /* setup stuff */ dtrace:::BEGIN { /* reverse sorting order */ setopt("aggsortrev"); /* starting values */ secs = DURATION; sys_read_count_e = 0; sys_write_count_e = 0; sys_read_count_r = 0; sys_write_count_r = 0; /* bzzz, krrr... */ printf("Tracing... Please wait.\n"); printf("["); } /* set filtering */ syscall::read:entry, syscall::write:entry { /* to filter or not to filter */ this->filter = FILTER ? 0 : 1; /* open filter for these */ (OPT_pid == 1 && PID == pid) ? this->filter = 1 : 1; (OPT_name == 1 && NAME == execname) ? this->filter = 1 : 1; } syscall::read:entry /this->filter/ { /* count number of calls */ sys_read_count_e += 1; /* record the file descriptor */ self->fd = arg0; /* process the return */ self->entered = 1; } syscall::read:return /self->entered/ { /* count number of calls */ sys_read_count_r += 1; @sys_read_pfd[pid, self->fd, execname] = count(); self->fd = -1; self->entered = 0; } syscall::write:entry /this->filter/ { /* count number of calls */ sys_write_count_e += 1; /* record the file descriptor */ self->fd = arg0; /* process the return */ self->entered = 1; } syscall::write:return /self->entered/ { /* count number of calls */ sys_write_count_r += 1; @sys_write_pfd[pid, self->fd, execname] = count(); self->fd = -1; self->entered = 0; } /* tralalalaaaa .. tralalalalaaaa */ profile:::tick-1sec { printf("."); secs--; } /* this is the final countdown! */ profile:::tick-1sec /secs == 0/ { printf("]\n"); /* print totals */ printf("\nTOTALS\n"); printf(" %-15s %26u\n", "READ ENTER", sys_read_count_e); printf(" %-15s %26u\n", "READ RETURN", sys_read_count_r); printf(" %-15s %26u\n", "WRITE ENTER", sys_write_count_e); printf(" %-15s %26u\n", "WRITE RETURN", sys_write_count_r); printf("\n"); /* print read call overview */ printf("\nREAD CALLS RET. PER FD\n"); printa(" %-5u %-5u %-15s %@15u\n", @sys_read_pfd); printf("\n"); /* print write call overview */ printf("\nWRITE CALLS RET. PER FD\n"); printa(" %-5u %-5u %-15s %@15u\n", @sys_write_pfd); printf("\n"); /* exiiiit */ exit(0); } '