我想显示脚本的完成时间。
我目前做的是——
#!/bin/bash
date ## echo the date at start
# the script contents
date ## echo the date at end
Run Code Online (Sandbox Code Playgroud)
这只是显示脚本开始和结束的时间。是否可以显示像处理器时间/ io 时间等细粒度的输出?
小智 688
只需time在调用脚本时使用:
time yourscript.sh
Run Code Online (Sandbox Code Playgroud)
Rob*_*Bos 273
如果time不是一个选项,
start=`date +%s`
stuff
end=`date +%s`
runtime=$((end-start))
Run Code Online (Sandbox Code Playgroud)
或者,如果您需要亚秒级精度并已bc安装,
start=`date +%s.%N`
stuff
end=`date +%s.%N`
runtime=$( echo "$end - $start" | bc -l )
Run Code Online (Sandbox Code Playgroud)
Sté*_*las 95
times退出脚本时无需参数即可调用。
使用ksh或zsh,您也可以time改用。使用zsh,time除了用户和系统CPU 时间之外,还将为您提供挂钟时间。
要保留脚本的退出状态,您可以:
ret=$?; times; exit "$ret"
Run Code Online (Sandbox Code Playgroud)
或者您也可以在EXIT以下位置添加陷阱:
trap times EXIT
Run Code Online (Sandbox Code Playgroud)
这样,每当 shell 退出时都会调用时间并保留退出状态。
$ bash -c 'trap times EXIT; : {1..1000000}'
0m0.932s 0m0.028s
0m0.000s 0m0.000s
$ zsh -c 'trap time EXIT; : {1..1000000}'
shell 0.67s user 0.01s system 100% cpu 0.677 total
children 0.00s user 0.00s system 0% cpu 0.677 total
Run Code Online (Sandbox Code Playgroud)
另请注意,所有bash,ksh和zsh都有一个$SECONDS特殊变量,每秒自动递增。在zsh和 中ksh93,该变量也可以设为浮点数(与typeset -F SECONDS)以获得更高的精度。这只是挂钟时间,而不是 CPU 时间。
小智 39
我有点晚了,但想发布我的解决方案(亚秒级精度),以防其他人通过搜索偶然发现这个线程。输出格式为天、小时、分钟,最后是秒:
res1=$(date +%s.%N)
# do stuff in here
res2=$(date +%s.%N)
dt=$(echo "$res2 - $res1" | bc)
dd=$(echo "$dt/86400" | bc)
dt2=$(echo "$dt-86400*$dd" | bc)
dh=$(echo "$dt2/3600" | bc)
dt3=$(echo "$dt2-3600*$dh" | bc)
dm=$(echo "$dt3/60" | bc)
ds=$(echo "$dt3-60*$dm" | bc)
LC_NUMERIC=C printf "Total runtime: %d:%02d:%02d:%02.4f\n" $dd $dh $dm $ds
Run Code Online (Sandbox Code Playgroud)
希望有人在那里发现这很有用!
Mar*_*ark 35
我的方法bash:
# Reset BASH time counter
SECONDS=0
#
# do stuff
#
ELAPSED="Elapsed: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"
Run Code Online (Sandbox Code Playgroud)
小智 19
就个人而言,我喜欢将所有脚本代码包装在一些“main”函数中,如下所示:
main () {
echo running ...
}
# stuff ...
# calling the function at the very end of the script
time main
Run Code Online (Sandbox Code Playgroud)
请注意time在这种情况下使用该命令是多么容易。显然,您没有测量包括脚本解析时间在内的精确时间,但我发现它在大多数情况下都足够准确。
小智 11
#!/bin/bash
start=$(date +%s.%N)
# HERE BE CODE
end=$(date +%s.%N)
runtime=$(python -c "print(${end} - ${start})")
echo "Runtime was $runtime"
Run Code Online (Sandbox Code Playgroud)
是的,这称为 Python,但如果您能接受它,那么这是一个非常不错的简洁解决方案。
zba*_*son 11
这个问题已经很老了,但在试图找到我最喜欢的方法时,这个线程出现了很高的......我很惊讶没有人提到它:
perf stat -r 10 -B sleep 1
Run Code Online (Sandbox Code Playgroud)
'perf' 是内核中包含在 'tools/perf' 下的性能分析工具,通常可以作为单独的软件包安装(CentOS 中的“perf”和 Debian/Ubuntu 上的“linux-tools”)。 Linux Kernal perf Wiki有更多关于它的信息。
运行 'perf stat' 给出了很多细节,包括最后的平均执行时间:
1.002248382 seconds time elapsed ( +- 0.01% )
Run Code Online (Sandbox Code Playgroud)
可以在命令之前添加一个小的 shell 函数来测量它们的时间:
tm() {
local start=$(date +%s)
$@
local exit_code=$?
echo >&2 "took ~$(($(date +%s)-${start})) seconds. exited with ${exit_code}"
return $exit_code
}
Run Code Online (Sandbox Code Playgroud)
然后在您的脚本或命令行中使用它,如下所示:
tm the_original_command with all its parameters
Run Code Online (Sandbox Code Playgroud)
接受的解决方案使用timewrites to stderr。使用写入的
解决方案。
使用的解决方案缺少亚秒级精度。
其他解决方案涉及调用外部程序,例如或 ,但效率不高。
如果您对其中任何一个都满意,请使用它。timesstdout$SECONDSdateperf
但是,如果您需要一个有效的解决方案来获取毫秒精度的时间,并需要将它们放入变量中,以便原始输出保持不受干扰,您可以将进程替换与一些重定向结合起来,time这比调用外部程序要快得多,并且允许围绕计时包装器进行重定向脚本与原始命令/脚本相同。
# Preparations:
Cmd=vgs # example of a program to be timed which is writing to stdout and stderr
Cmd="eval { echo stdout; echo stderr >&2; sleep 0.1; }" # other example; replace with your own
TIMEFORMAT="%3R %3U %3S" # make time output easy to parse
Run Code Online (Sandbox Code Playgroud)
选择以下变体之一,解析time适合您需要的输出:
最短变体,其中stdoutof$Cmd被写入stderr且不写入任何内容stdout:
read Elapsed User System < <({ time $Cmd 2>&3; } 3>&2 2>&1 >&3)
Run Code Online (Sandbox Code Playgroud)
更长的变体,保持原始stdout且stderr彼此分离:
{ read Elapsed User System < <({ time $Cmd 2>&4; } 4>&2 2>&1 >&3); } 3>&1
Run Code Online (Sandbox Code Playgroud)
最复杂的变体包括关闭额外的文件描述符,这样就$Cmd好像没有这个定时包装器一样调用它,并且lvm命令vgs不抱怨泄漏的文件描述符:
{ read Elapsed User System < <({ time $Cmd 2>&4 4>&-; } 4>&2 2>&1 >&3 3>&-); } 3>&1
Run Code Online (Sandbox Code Playgroud)
bash您甚至可以在不调用的情况下伪造浮点加法bc,这会慢得多:
CPU=`printf %04d $((10#${User/.}+10#${System/.}))` # replace with your own postprocessing
echo CPU ${CPU::-3}.${CPU: -3} s, Elapsed $Elapsed s >&2 # redirected independent of $Cmd
Run Code Online (Sandbox Code Playgroud)
$Cmd在慢速 CPU 上的两个示例的可能输出:
File descriptor 3 (/dev/pts/1) leaked on vgs invocation. Parent PID 10756: bash
File descriptor 4 (/dev/pts/1) leaked on vgs invocation. Parent PID 10756: bash
VG #PV #LV #SN Attr VSize VFree
b3 3 24 0 wz--n- 1.31t 1.19t
CPU 0.052 s, Elapsed 0.056 s
Run Code Online (Sandbox Code Playgroud)
或者:
stdout
stderr
CPU 0.008 s, Elapsed 0.109 s
Run Code Online (Sandbox Code Playgroud)
小智 5
#!/bin/csh
#PBS -q glean
#PBS -l nodes=1:ppn=1
#PBS -l walltime=10:00:00
#PBS -o a.log
#PBS -e a.err
#PBS -V
#PBS -M shihcheng.guo@gmail.com
#PBS -m abe
#PBS -A k4zhang-group
START=$(date +%s)
for i in {1..1000000}
do
echo 1
done
END=$(date +%s)
DIFF=$(echo "$END - $START" | bc)
echo "It takes DIFF=$DIFF seconds to complete this task..."
Run Code Online (Sandbox Code Playgroud)
只需使用time [any command]. 例如:time sleep 1将实时睡眠(即:由秒表计时)约 1.000 到约 1.020 秒,如下所示:
$ time sleep 1
real 0m1.011s
user 0m0.004s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
多么美好的事情。你可以在它后面放置任何命令,它会以一种漂亮的、人类可读的形式输出结果。我真的很喜欢将它用于计时构建。前任:
# time your "make" build
time make
# time your "Bazel" build
time bazel build //path/to/some:target
Run Code Online (Sandbox Code Playgroud)
...或者对于可能很长的 git 操作,所以我可以制定切合实际的心理期望:
# time how long it takes to pull from a massive repo when
# I'm working from home during COVID-19. NB: `git pull`
# is sooooo much slower than just pulling the one branch
# you need with `git pull origin <branch>`, so just fetch
# or pull what you need!
time git pull origin master
Run Code Online (Sandbox Code Playgroud)
对于更自定义的计时需求,您可能需要在 bash 中操作输出或将其转换为其他形式,请使用内部$SECONDS变量。这是一个演示,包括将这些秒转换为其他单位,例如浮点分钟:
请注意,在这种情况下dt_min从0.01666666666...(1 秒 = 那么多分钟)四舍五入,0.017因为我正在使用该printf函数进行四舍五入。sleep 1;下面的部分是您调用脚本运行和计时的地方,但为了这个演示,我只是睡了 1 秒钟。
命令:
start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); \
dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); \
echo "dt_sec = $dt_sec; dt_min = $dt_min"
Run Code Online (Sandbox Code Playgroud)
输出:
dt_sec = 1; dt_min = 0.017
Run Code Online (Sandbox Code Playgroud)
bc和printf我的回答:https : //stackoverflow.com/questions/12722095/how-do-i-use-floating-point-division-in-bash/58479867#58479867time命令,但它可能来自@Trudbert 的回答就在这里。使用内置的 bash 时间吗?
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.
Run Code Online (Sandbox Code Playgroud)
例子:
TIMEFORMAT="The command took %Rs"
time {
sleep 0.1
}
Run Code Online (Sandbox Code Playgroud)
输出:
The command took 0.108s
Run Code Online (Sandbox Code Playgroud)