How to wrap a command to measure its elapsed time?
Currently I do it using eval
:
do_cmd_named()
{
local name=$1
local cmd=$2
echo "$name"
local start_time=$(date +%s)
eval "$cmd 2>&1"
local exit_status=$?
local end_time=$(date +%s)
local elapsed_time_sec=$((end_time-start_time))
local elapsed_time_min_sec=$(date -ud "@$elapsed_time_sec" +'%M:%S')
if [[ $exit_status -ne 0 ]]
then
echo "$name failed with exit status $exit_status (elapsed time $elapsed_time_min_sec)"
return $exit_status
else
echo "$name done (elapsed time $elapsed_time_min_sec)"
fi
}
job()
{
sleep 1
}
do_cmd_named "do job" "job"
which leads to:
do job
do job done (elapsed time 00:01)
For my cases this approach almost works. However, this approach is considered bad because it violates some rules from BashFAQ. For example, "don't put code inside variables" from BashFAQ #50 (see also BashFAQ #48).
So, the question is: how to do it correctly?
time
be good enough? See How to get execution time of a script effectively? and How to measure time of program execution and store that inside a variable. – Stephen Kitt Nov 21 '22 at 09:33cmd1 | cmd2
orwhile cmd1; do cmd2; done
? 1, 2 and 3 for each of cmd1 and cmd2 or 1, 2 and 3 for the whole construct? – muru Nov 21 '22 at 12:51do_cmd_named name "while cmd1; do cmd2; done"
, why not dostart_cmd name; while cmd1; do cmd2; done; end_cmd
, with a suitablestart_cmd
andend_cmd
function? Why does it have to be the former? – muru Nov 21 '22 at 13:26start_time
andend_time
making possible to measure elapsed time for nested invocations (demo). – pmor Nov 22 '22 at 08:32