This is my first serious shell script, so it is probably horrible.
Problem statement
I decided to improve my profiling skills as so far they were mostly about hand-rolling counters and timers. After trying out better profiling tools and techniques I noticed that previously I was just rolling my face over keyboard until the metrics got better. Yet to do profiling in a consistent and hassle-free way is a bit tedious.
perf
is a profiling utility used to collect software and hardware metrics about program's execution or entirety of the machine. It outputs binary files that can be fed into variety of tools, but I decided on FlameGraph. The problem with it is that it takes several commands and the overall process is rather boring. I decided to automate it with a shell script that invokes needed commands with the flags I usually use.
Code
#!/bin/sh
usage="$(basename "$0") [-g fgdir] [-h] -t target
where:
-h show this help text
-t executable to run under perf
-g root directory of FlameGraph repository https://github.com/brendangregg/FlameGraph
"
fgroot="."
while getopts 'g:ht:' option; do
case "$option" in
h) echo "$usage"
exit
;;
t) if ! [ -x "$(command -v "$OPTARG")" ]; then
echo "$OPTARG is not executable"
exit 1
fi
echo "$OPTARG"
target="$OPTARG"
;;
g) fgroot="$OPTARG"
echo "$OPTARG"
;;
:) printf "missing argument for -%s\n" "$OPTARG" >&2
echo "$usage" >&2
exit 1
;;
\?) printf "illegal option: -%s\n" "$OPTARG" >&2
echo "$usage" >&2
exit 1
;;
esac
done
shift $((OPTIND - 1))
scpath="$fgroot/stackcollapse-perf.pl"
fgpath="$fgroot/flamegraph.pl"
echo "$scpath" "$fgpath"
if ! [ "$(command -v "$scpath")" ]; then
printf "could not find stackcollapse-perf.pl\n"
exit 1
fi
if ! [ "$(command -v "$fgpath")" ]; then
printf "could not find flamegraph.pl\n"
exit 1
fi
#filename=$(date +"%Y-%m-%d-%Hh-%Mm-%Ss").perf
filename=$(date -u +"%Y-%m-%dT%H:%M:%S%Z")
perf record -g --call-graph=dwarf -F 99 "$target"
perf script > "$filename".perf
$scpath "$filename".perf > "$filename".collapsed
$fgpath "$filename".collapsed > "$filename".svg
Is the interface idiomatic (command line argument letters, usage string, etc)? Is it possible to write the shell script in an easier to understand way? Is there any more useful checking I should do inside my code?
Sample output: