Forcing an 'added' alias to every command
You can record the time a command line is started and the time a prompt is displayed. Bash already keeps track of the starting date of each command line in its history, and you can note the time when you display the next prompt.
print_command_wall_clock_time () {
echo Wall clock time: \
$(($(date +%s) - $(HISTTIMEFORMAT="%s ";
set -o noglob;
set $(history 1); echo $2)))
}
PROMPT_COMMAND=print_command_wall_clock_time$'\n'"$PROMPT_COMMAND"
This only gives you second resolution, and only the wall clock time. If you want better resolution, you need to use an external date
command that supports the %N
format for nanoseconds, and the DEBUG
trap to call date
before running the command to time.
call_date_before_command () {
date_before=$(date +%s.%N)
}
print_wall_clock_time () {
echo "Wall clock time: $(date +"%s.%N - $date_before" | bc)"
}
trap call_date_before_command DEBUG
PROMPT_COMMAND=print_wall_clock_time
Even with the DEBUG
trap, I don't think there's a way of automatically displaying processor times for each command, or being more discriminating than prompt to prompt.
If you're willing to use a different shell, here's how to get a time report for every command in zsh (this doesn't generalize to other tasks):
REPORTTIME=0
You can set REPORTTIME
to any integer value, the timing information will only be displayed for commands that used more than this many seconds of processor time.
Zsh took this feature from csh where the variable is called time
.
Your options here are going to depend on your shell. In zsh
there a convenient hook function called preexec()
that is run right before any interactive shell commands. By creating a function with this name, you can cause things to be executed. You can also follow up with a function called precmd()
which will run just before the next prompt is drawn, which will be right after your command finishes.
By creating this pair of functions, you can have whatever arbitrary commands you want run before and after whatever commands are issued at the prompt. You could use this to log shell usage, create locks, test the environment, or as in your example calculate time or resources spent while a command runs.
In this example, we will create ourselves a benchmark timestamp before running a command using preexec()
then calculate the time spent executing the command using precmd()
and output it before the prompt or log it away. Example:
preexec() {
CMDSTART=$(date +%s%N)
}
precmd() {
CMDRUNTIME=$(($(date +%s%N)-$CMDSTART))
echo "Last command ran for $CMDRUNTIME nanoseconds."
}
Note: For this particular example, there is an even easier builtin function. All you have to do is turn on runtime reporting in ZSH and it will do this automatically.
$ export REPORTTIME=0
$ ls -d
./
ls -BF --color=auto -d 0.00s user 0.00s system 0% cpu 0.002 total
In a more practical implementation of preexec()
, I use it see if the shell is running inside tmux
or screen
and, if so, to send information about the currently running command upstream to be displayed in the tab name.
Unfortunately in bash this little mechanism doesn't exist. Here is one man's attempt to replicate it. Also see Gilles's answer for similar nifty little hack.