如何在shell脚本中测量时间的持续秒数?

84

我想知道在Linux shell脚本中执行一个操作需要多长时间。我该如何做到这一点?

6个回答

130

如其他人所建议的那样,使用time命令是个好主意。

另一个选项是使用神奇的内置变量$SECONDS,它包含了自脚本开始执行以来经过的秒数。你可以这样说:

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

我认为这是特定于bash的,但由于你在使用Linux,所以我假设你正在使用bash。


5
这里唯一需要注意的是,在自己的变量名中使用全大写字母是不好的形式,因为这意味着你可能会错误地覆盖Shell内置变量(例如,如果有人分配给SECONDS,它就不再有其特殊含义)。请参阅POSIX规范@http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html,将小写字母保留给应用程序使用,并记住Shell和环境变量共享单个名称空间--*含小写字母的环境变量名称名称空间保留给应用程序使用。* - Charles Duffy

42

使用time命令,执行time ls /bin命令。


1
当您执行复杂命令序列时,time不太适用。 - Shiplu Mokaddim
4
不行吗?那这样怎么样:time (ls /; sleep 2; ls /bin) - Keith
如果您使用\(),它会变得更加复杂。 - Shiplu Mokaddim
3
@shiplu.mokadd.im - 为何不适合?请解释一下。对我来说似乎很好/准确,并且我已经使用了多年... - B. Shea
1
@Keith 这里有一些问题,比如 /usr/bin/time -f '%C => %E' (ls / ; sleep 2; ls /bin) 会抛出 bash: syntax error near unexpected token '(' - Shiplu Mokaddim
无法在time'd命令中使用管道(grep过滤器)使其正常工作。 - JeffRSon

41

尝试下面的例子:

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

16
许多答案提到了$SECONDS,但实际上这个变量比他们意识到的更好
将值分配给此变量会将计数重置为分配的值,并且扩展值成为分配的值加上自分配以来的秒数。
这意味着您可以直接查询该变量,在脚本结束时打印经过的时间:
#!/usr/bin/env bash

# Do stuff...

echo "Script finished in $SECONDS seconds."

你也可以像这样定时较小的部分:

#!/usr/bin/env bash

# Do stuff

SECONDS=0

# Do timed stuff...

echo "Timed stuff finished in $SECONDS seconds."

6

以下是查找以毫秒为单位经过的时间的脚本。将 sleep 60 行替换为您想要执行的代码。

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

1

GNU time

我也是 GNU time 命令的忠实粉丝:https://www.gnu.org/software/time/,与 Bash 内置的 time 相比,它提供了一些重要的选项。

使用示例:

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

输出:

1.00

解释:

  • env: 查找/usr/bin/time而不是Bash内置的time命令。

  • --format '%e': 以秒为单位打印时间,参见man time

    在进行基准测试时,这通常是我想要的:一个单独的数字而不是分钟+秒。

我经常使用的一个重要模式是:

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.

输出:

cmd sleep 1
time 1.00

cmd sleep 2
time 2.00

cmd sleep 3
time 3.00

解释:

  • --output:将时间输出到文件。

    默认情况下,输出会发送到stderr,因此这个选项对于将时间与命令的stderr分开很重要。

  • --append:追加到文件而不是覆盖。

    这使我可以将整个基准测试输出集中在一个文件中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接