在shell中获取程序执行时间

我想在一些不同的条件下在linux shell中执行一些东西,并且能够输出每次执行的执行时间。

我知道我可以写一个perl或python脚本,可以做到这一点,但有一种方法我可以在shell中做到这一点吗?(恰好是bash)

449098 次浏览

使用内置的time关键字:

$ help time


time: time [-p] PIPELINE
Execute PIPELINE and print a summary of the real time, user CPU time,
and system CPU time spent executing PIPELINE when it terminates.
The return status is the return status of PIPELINE.  The `-p' option
prints the timing summary in a slightly different format.  This uses
the value of the TIMEFORMAT variable as the output format.

例子:

$ time sleep 2
real    0m2.009s
user    0m0.000s
sys     0m0.004s

你可以得到比bash内置的time(即Robert Gamble提到的时间(1))更详细的信息。通常这是/usr/bin/time

< p > <一口>编者按: 为了确保调用的是外部效用 time,而不是shell的time 关键字,请将其作为/usr/bin/time调用。 time是一个POSIX-mandated效用,但它需要支持的唯一选项是-p。 特定的平台实现特定的、非标准的扩展:-vGNUtime实用程序一起工作,如下所示(问题标记为);BSD/macOS实现使用-l产生类似的输出-参见man 1 time.

详细输出示例:

$ /usr/bin/time -v sleep 1
Command being timed: "sleep 1"
User time (seconds): 0.00
System time (seconds): 0.00
Percent of CPU this job got: 1%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.05
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 0
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 210
Voluntary context switches: 2
Involuntary context switches: 1
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

如果你打算以后使用这些时间来计算,请学习如何使用/usr/bin/time-f选项来输出节省时间的代码。下面是我最近使用的一些代码,用于获取和排序整个班级的学生程序的执行时间:

fmt="run { date = '$(date)', user = '$who', test = '$test', host = '$(hostname)', times = { user = %U, system = %S, elapsed = %e } }"
/usr/bin/time -f "$fmt" -o $timefile command args...

我后来连接了所有的$timefile文件,并将输出管道到一个Lua解释器。你可以用Python或bash或任何你喜欢的语法做同样的事情。我喜欢这个技巧。

方法是

$ > g++ -lpthread perform.c -o per
$ > time ./per

输出为>>

real    0m0.014s
user    0m0.010s
sys     0m0.002s
#!/bin/bash
START=$(date +%s)
# do something
# start your script work here
ls -R /etc > /tmp/x
rm -f /tmp/x
# your logic ends here
END=$(date +%s)
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"

如果你想要更精确,使用%Ndate(并使用bc作为diff,因为$(())只处理整数)。

以下是如何做到这一点:

start=$(date +%s.%N)
# do some stuff here
dur=$(echo "$(date +%s.%N) - $start" | bc)


printf "Execution time: %.6f seconds" $dur

例子:

start=$(date +%s.%N); \
sleep 0.1s; \
dur=$(echo "$(date +%s.%N) - $start" | bc); \
printf "Execution time: %.6f seconds\n" $dur

结果:

Execution time: 0.104623 seconds

对于逐行增量测量,请尝试日晷

$ npm install -g gnomon
$ <your command> | gnomon --medium=1.0 --high=4.0 --ignore-blank --real-time=100

一个命令行实用程序,有点像moreutils的ts,用于将时间戳信息预先添加到另一个命令的标准输出中。对于长时间运行的流程非常有用,因为您需要记录花费如此长时间的事情。

你也可以使用--high和/或--medium选项来指定以秒为单位的长度阈值,超过该阈值,gnomon将用红色或黄色突出显示时间戳。你还可以做一些其他的事情。

example

你可以使用time亚层 ():

time (
for (( i=1; i<10000; i++ )); do
echo 1 >/dev/null
done
)

或者在同一个shell {}中:

time {
for (( i=1; i<10000; i++ )); do
echo 1 >/dev/null
done
}

如果你只需要精确到秒,你可以使用内置的$SECONDS变量,它会计算shell已经运行的秒数。

while true; do
start=$SECONDS
some_long_running_command
duration=$(( SECONDS - start ))
echo "This run took $duration seconds"
if some_condition; then break; fi
done

一个可能简单的方法(可能不能满足不同用户的需求)是使用shell PROMPT。这是一个简单的解决方案,在某些情况下可能有用。你可以使用bash提示功能,如下例所示:

export PS1='[\t \u@\h]\$' 

The above command will result in changing the shell prompt to :

[HH:MM:SS username@hostname]$ 

每次运行命令(或按回车键)返回到shell提示符时,提示符将显示当前时间。

< p > 注: < br > 1)注意,如果你在键入下一个命令之前等待了一段时间,那么这个时间需要考虑,即shell提示符中显示的时间是shell提示符显示时的时间戳,而不是你输入命令时的时间戳。一些用户选择按Enter键,在他们准备好下一个命令之前,获得一个带有新时间戳的新提示符 2)还有其他可用的选项和修饰符可以用来改变bash提示符,更多细节请参阅(man bash)。