如何在 shell 脚本中度量以秒为单位的持续时间?

我希望了解 Linux shell 脚本中的一个操作需要多长时间?

63779 次浏览

Use the time command. time ls /bin.

Using the time command, as others have suggested, is a good idea.

Another option is to use the magic built-in variable $SECONDS, which contains the number of seconds since the script started executing. You can say:

START_TIME=$SECONDS
dosomething
ELAPSED_TIME=$(($SECONDS - $START_TIME))

I think this is bash-specific, but since you're on Linux, I assume you're using bash.

Try following example:

START_TIME=$SECONDS
# do something
sleep 65


ELAPSED_TIME=$(($SECONDS - $START_TIME))


echo "$(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"
#> 1 min 5 sec

Here is the script to find the time elapsed in milliseconds. Replace the sleep 60 line with the code you want to execute.

a=0
while [ $a -lt 10 ]
do
START_TIME=`echo $(($(date +%s%N)/1000000))`
sleep 3
END_TIME=`echo $(($(date +%s%N)/1000000))`
ELAPSED_TIME=$(($END_TIME - $START_TIME))
echo $ELAPSED_TIME
if [ $a -eq 10 ]
then
break
fi
a=`expr $a + 1`
done

Many of the answers mention $SECONDS, but that variable is actually even better than they realize:

Assignment to this variable resets the count to the value assigned, and the expanded value becomes the value assigned plus the number of seconds since the assignment.

This means you can simply query this variable directly at the end of your script to print the elapsed time:

#!/usr/bin/env bash


# Do stuff...


echo "Script finished in $SECONDS seconds."

You can also time smaller sections like so:

#!/usr/bin/env bash


# Do stuff


SECONDS=0


# Do timed stuff...


echo "Timed stuff finished in $SECONDS seconds."

GNU time

I'm also a big fun of the GNU time command: https://www.gnu.org/software/time/ which offers some important options compared to the time Bash built-in.

Sample usage:

env time --format '%e' --output time.log sleep 1

Output:

1.00

Explanation:

  • env: to find /usr/bin/time instead of the Bash built-in

  • --format '%e': print time in seconds, see man time.

    This is often what I want when benchmarking: a single number rather than minutes + seconds.

And an important pattern I often use is:

bench-cmd() (
logfile=time.log
echo "cmd $@" >> "$logfile"
printf 'time ' >> "$logfile"
bench_cmd="env time --append --format '%e' --output '$logfile' $@"
eval "$bench_cmd"
echo >> "$logfile"
)


rm -f time.log
bench-cmd sleep 1
bench-cmd sleep 2
bench-cmd sleep 3
cat time.log

GitHub upstream.

Output:

cmd sleep 1
time 1.00


cmd sleep 2
time 2.00


cmd sleep 3
time 3.00

Explanation:

  • --output: output the time to a file.

    By default, the output goes to stderr, so this option is important to separate the timing from the stderr of the command.

  • --append: append to the file instead of overwriting.

    This allows me to concentrate the entire benchmark output in a single file.