In its simplest form, this sounds like what you're after.
now(){
date -u +%s.%N
}
measure_time(){
local elapsed="$(bc <<<"$end_time-$start_time")"
echo "Total of $elapsed seconds elapsed for process"
}
start_time="$(now)"
sleep 5
end_time="$(now)"
measure_time
You could make the now
function accept a named variable and adapt the measure_time
function to handle that, but it would be an unnecessary complication if your use case is to track one process at a time.
Having said that, here's an iteration in that direction. start
and end
are arbitrary labels, so you could call them what ever suits, if you were tracking multiple events.
stamp(){
time[$1]="$(date -u +%s.%N)"
}
measure_time(){
local elapsed="$(bc <<<"${time[$2]}-${time[$1]}")"
echo "Total of $elapsed seconds elapsed for process"
}
declare -A time=()
stamp start
sleep 5
stamp end
measure_time start end
EDIT:
Caveat
As the figures in roaima's answer show, this is not going to be high precision, because each action (particularly so sub shells and external processes) will pad the reported time out by some fraction of a second. This probably doesn't matter for multi-minute processes (in which case why measure nano seconds?) but will become more pronounced at lower run times, to the point of being almost meaningless. Though the problem was rather less severe in my tests as compared to roaima's. It rather depends on what you are using that data for.
ANOTHER EDIT:
Responding to QuartzCrystal's fair comment, herein lies a further iteration which, it turns out, is converging on roaima's answer -- probably indicating they are on the "best" track.
_stamp(){
time[${1:?}]="$(date -u +%s.%N)"
}
_start() {
_stamp "start${1:+_${1}}"
}
_end() {
_stamp "end${1:+_${1}}"
}
measure_time(){
local elapsed="$(bc <<<"${time[end${1:+_${1}}]}-${time[start${1:+_${1}}]}")"
echo "Total of $elapsed seconds elapsed${1:+ for process ${1}}"
}
declare -A time=()
_start
sleep 5
_end
measure_time
_start foo
sleep 1
_start bar
sleep 2
_end foo
_end bar
measure_time foo
measure_time bar
hello() { sleep 1; echo hi; }
And you use:value=$(hello) ; echo $value
The output will behi
SECONDS
variable - see for example Time elapsed of a bash script (days/minutes/seconds)time
inside a script (also on a function)? Seetype time
,help time
andman time
. General usetime MyExecutableScript.sh
ortime /bin/bash MyScript.sh
. In your script can be something likeMyFunction(){....}
thentime MyFunction
orA="$((time MyFunction) 2>&1)"
. Note that you need a subshell(...)
to redirect the output of time.