我想在Linux shell中在几个不同的条件下执行一些东西,并且能够输出每次执行的执行时间。
我知道我可以编写一个Perl或python脚本来完成这个任务,但是有没有一种方法可以在shell中完成呢?(恰巧是巴什)
Windows案例:stackoverflow.com/questions/673523/…
有没有可能像Windows那样获得Ticks?
unix.stackexchange.com/questions/52313/…
使用内置的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
这是如何在像time -p i=x; while read line; do x=x; done < /path/to/file.txt这样的命令上使用的?它立即返回0.00,除非我不在while循环之前放置任何内容。给出了什么?
这是糟糕的"时间"版本,bash builtin。外部"时间"命令在哪里?
@znik,试试/usr/bin/time
@natli:虽然time可以对整个管道按原样计时(由于是bash关键字),但您需要使用group命令({ ...; ...; }对多个命令计时:time -p { i=x; while read line; do x=x; done < /path/to/file.txt; }。
您可以像这样测量管道命令和脚本的时间,即时间ls | grep MyFolder或我们的脚本脚本,即时间myscript.sh。
要查看系统上安装的所有时间版本,可以使用type -a time。
您可以得到比bash内置的time更详细的信息(robert gamble提到)使用时间(1)。通常这是/usr/bin/time。
编者按:为了确保调用外部实用程序time,而不是shell的time关键字,请将其作为/usr/bin/time调用。time是一个POSIX授权的实用程序,但它需要支持的唯一选项是-p。特定平台实现特定的、非标准的扩展:-v与GNU的time实用程序一起工作,如下所示(问题被标记为Linux);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
你不会碰巧知道Debian软件包是什么?默认情况下似乎没有安装
我提到了你的职位罗伯特。除非您的意思是您建议的命令不是bash内置的?
令人惊讶的是,它是从一个叫做"时间"的软件包中安装的。
来自/usr/bin/time的输出看起来像"0.00用户0.00系统0:02.00已用0%CPU(0avgtext+0avgdata 0maxresident)k 0输入+0输出(0major+172minor)页面故障0交换"
@grepsedawk:我使用的time命令是bash内置命令,您提供手册页的time(1)命令不是内置命令,而是单独的独立程序,我认为您混淆了这两个命令。
@尼克:"sudo适合安装时间"。
不管怎样,+1是因为我从来没有使用过/usr/bin/time,因为它的输出很难看,但是现在我知道了如何获得格式良好的输出,它提供了许多其他有用的信息(我不希望从名为"time"的命令得到这些信息)。
这不允许对shell构造进行计时,例如,time { sleep 10; echo hi; sleep 10; }。只有壳牌的timer才有能力做到这一点。你可以争辩说/usr/bin/time bash -c 'sleep 10; echo hi; sleep 10;'会起作用。够公平的。
任何一个Linux专家都知道如何在重定向(如EDOCX1)(10))中使用它吗?
为什么which time给我的是/usr/bin/time,而Bash的时间却被time叫了?(按照您的建议,在命令中指定完整路径会得到正确的结果。)
#!/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"
有更简单的方法。bash自动计算特殊变量$seconds,然后不需要根据外部日期命令重新计算。$seconds变量保持bash脚本启动时运行的秒数。这个变量有一些特殊的属性。见人页:D
我在评论中尝试了上述两种方法。在第一个变量中,我得到一个"非法变量"错误;第二个变量中,我得到"未识别变量"
对于逐行增量测量,请尝试gnomon。
A command line utility, a bit like moreutils's ts, to prepend timestamp information to the standard output of another command. Useful for long-running processes where you'd like a historical record of what's taking so long.
您还可以使用--high和/或--medium选项指定以秒为单位的长度阈值,在该阈值上,gnomon将以红色或黄色突出显示时间戳。你也可以做一些其他的事情。
很好的提示,但要明确一点:这对逐行计时很有用,但是采用这种细粒度计时的开销显著增加了总体计时。
很棒的实用工具……谢谢分享
伟大的GIF!谢谢你的努力
如果您希望更精确,请使用%N和date进行比较(并使用bc进行比较,因为$(())只处理整数)。
方法如下:
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
" $dur
结果:
Execution time: 0.104623 seconds
如果您打算稍后使用时间进行计算,请学习如何使用/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或您最喜欢的任何语法执行相同的操作。我喜欢这种技巧。
注:完整路径/usr/bin/time是必要的,因为虽然which time会告诉你,否则,如果你只运行time,它会运行你的shell版本的time,它不接受任何参数。
如果只需要精确到第二个,可以使用内置的$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
您可以使用time和subshell ():
time (
for (( i=1; i<10000; i++ )); do
echo 1 >/dev/null
done
)
或在同一壳体中,{}:
time {
for (( i=1; i<10000; i++ )); do
echo 1 >/dev/null
done
}
您发布了两个相同的代码片段。你一定是想在那里有所不同。
@stasbekman不是真的,首先使用(和)(新上下文,子shell),其他使用{和}(相同shell,相同上下文)
啊哈!我很认真地看了看这两个,没有看到区别。感谢您澄清vs()。
方式是
$ > g++ -lpthread perform.c -o per
$ > time ./per
输出>
real 0m0.014s
user 0m0.010s
sys 0m0.002s
不需要使用-lphtread或-o标签。只需要使用time命令,这个公认的答案解释得更好。
这是一个例子,这就是我的perform.c有线程,所以我需要-lpthread,对于简单的标识,它是-o per。
我喜欢您的解决方案如何包括线程。
一个可能很简单的方法(可能不满足不同的用户需求)是使用shell prompt。它是一个简单的解决方案,在某些情况下可能很有用。您可以使用bash提示功能,如下例所示:
export PS1='[\t \u@\h]\$'
上述命令将导致将shell提示更改为:
[HH:MM:SS username@hostname]$
每次运行返回shell提示的命令(或按Enter键)时,该提示将显示当前时间。
笔记:1)请注意,如果在键入下一个命令之前等待了一段时间,则需要考虑这一时间,即shell提示中显示的时间是shell提示显示时的时间戳,而不是输入命令时的时间戳。有些用户选择按Enter键以在准备下一个命令之前获得带有新时间戳的新提示。2)还有其他可用于更改bash提示的选项和修改器,请参阅(man bash)了解更多详细信息。
不是程序执行的时间点,而是程序执行的持续时间。