#!/bin/sh # # ktrace # Reset and enable kernel tracing # Run command in background, if specified # Sleep for duration, if specified # Wait for command completion, timeout, or keyboard interrupt # (Note: keyboard interrupt kills command) # Disable kernel tracing # Extract kernel trace buffer # Reset kernel tracing, if specified # TMPDIR=${TMPDIR:-/tmp} output_file=$TMPDIR/ktrace.tnf buffer_size=512k duration= events= command= do_reset=y child= alarm= # usage message usage() { echo "" echo $1 echo " Usage: ktrace [-o <output_file>] # default /tmp/ktrace.tnf [-s <buffer_size>] # default 512k -e <events> # kernel probes (keys) to enable [-r] # don't reset kernel tracing # default is to reset after command <cmd> | -t <seconds> Eg, # ktrace -e `thread vm io' -t 10 # ktrace -e `thread' -s 256k myapp ... " exit 1 } # failure message fail() { while [ $# -gt 0 ] do echo $1 shift done echo "ktrace failed" exit 2 } # Reset kernel tracing ktrace_reset() { if [ $1 = "y" ]; then echo "Resetting kernel tracing" prex -k >/dev/null 2>&1 <<-EOF ktrace off untrace /.*/ disable /.*/ buffer dealloc EOF test $? -ne 0 && fail "Could not reset kernel tracing" \ "`su root' and retry" fi } # Enable kernel tracing ktrace_on() { echo "Enabling kernel tracing" prex -k >/dev/null 2>&1 <<-EOF buffer alloc $buffer_size trace $events enable $events ktrace on EOF test $? -ne 0 && fail "Could not enable kernel tracing" \ "Check syntax of `-e' argument" \ "Check buffer size is not too high" } # Disable kernel tracing ktrace_off() { prex -k >/dev/null 2>&1 <<-EOF ktrace off EOF test $? -ne 0 && fail "Could not disable kernel tracing" echo "Kernel tracing disabled" } # Extract kernel trace buffer ktrace_xtract() { echo "Extracting kernel trace buffer" tnfxtract $output_file || fail "Could not extract kernel trace buffer" ls -l $output_file } # Run command, sleep for duration, or wait for command to complete run_command() { trap `interrupt' 0 1 2 3 15 if [ "$command" ]; then $command & child=$! echo "`$command' pid is $child" fi if [ "$duration" ]; then sleep $duration & alarm=$! wait $alarm # XXX test -z "$child" || kill -15 $child else wait $child fi trap 0 1 2 3 15 } # Keyboard interrupt interrupt() { test -z "$alarm" || kill -15 $alarm test -z "$child" || kill -15 $child } # Parse options while getopts o:s:t:e:r opt do case $opt in o) output_file="$OPTARG";; s) buffer_size="$OPTARG";; t) duration="$OPTARG";; e) events="$OPTARG";; r) do_reset="n";; \?) usage;; esac done shift `expr $OPTIND - 1` # Get command to run test $# -gt 0 && command="$*" # Check and normalize options test -z "$events" && usage "No kernel events specified" test -z "$command" && test -z "$duration" && \ usage "No command or time duration specified" # Perform experiment ktrace_reset y # Reset kernel tracing ktrace_on # Enable kernel tracing run_command # Run command, wait, or sleep ktrace_off # Disable kernel tracing ktrace_xtract # Extract buffer ktrace_reset $do_reset # Reset kernel tracing again exit 0 |