Bash 与 csh 的 time 计时用法:让长时间命令的耗时更易读
本文总结Bash与csh/tcsh中time的计时方法。Bash通过TIMEFORMAT定制输出,%0lR可得“1m5s”;csh通过set time设置格式,%E默认显示“1:05”。若想输出“?m?s”或“?:?”,可用SECONDS、EPOCHREALTIME或awk自行换算。文章还给出后处理VCS日志CPU Time的示例,将秒数转为分秒,便于阅读长时间命令耗时。

日常跑脚本、编译、仿真时,我们经常需要知道一条命令到底跑了多久。
Bash 和 csh/tcsh 都提供了内建的 time,但输出格式和定制方式差别很大。
这篇文章会总结两者的用法,并重点给出如何输出 ?m?s(如 1m5s)或 ?:?(如 1:05)这类适合阅读长时间计时的样式。


一、Bash 的 time

1. 基本用法

Bash 的 time 是一个 保留字,可以直接加在管道前面:

time sleep 1

输出默认到 stderr:

real    0m1.003s
user    0m0.001s
sys     0m0.002s
  • real:实际经过时间(墙钟时间)

  • user:用户态 CPU 时间

  • sys:内核态 CPU 时间

2. 自定义格式:TIMEFORMAT

Bash 用 TIMEFORMAT 控制 time 的输出格式。
常用占位符:

占位符含义
%Rreal 时间,秒
%Uuser 时间,秒
%Ssys 时间,秒
%PCPU 占用百分比
%lRreal 长格式,如 1m5.003s
%lUuser 长格式
%lSsys 长格式

注意:l 是 小写字母 L,不是数字 1。

输出 ?m?s 样式

设置:

TIMEFORMAT='耗时 %0lR'
time sleep 65

输出:

耗时 1m5s

%0lR 表示长格式、0 位小数,所以是 1m5s 而不是 1m5.003s。

如果想同时看用户/系统时间:

TIMEFORMAT='real=%0lR  user=%0lU  sys=%0lS'
time sleep 65

输出:

real=1m5s  user=0m0s  sys=0m0s

输出 ?:? 样式(如 1:05)

TIMEFORMAT 本身不能直接输出 1:05,因为长格式固定是 1m5s。
如果一定要 分:秒,可以用 SECONDS 或 EPOCHREALTIME 自己算。

方法一:整数秒(SECONDS)

SECONDS=0
sleep 65
printf '耗时 %d:%02d\n' $((SECONDS/60)) $((SECONDS%60))

输出:

耗时 1:05

方法二:高精度(EPOCHREALTIME,Bash 5.0+)

start=$EPOCHREALTIME
sleep 65.123
end=$EPOCHREALTIME

awk -v s="$start" -v e="$end" 'BEGIN {
    t = e - s
    m = int(t / 60)
    sec = t - m * 60
    printf "耗时 %d:%05.2f\n", m, sec
}'

输出:

耗时 1:05.12

3. 计时一组命令或管道

time {
  command1
  command2
}

计时整个管道:

time ( command1 | command2 )

只计时管道中的某一段:

command1 | { time command2; }

二、csh / tcsh 的 time

csh/tcsh 也有内建 time,但它是 命令,不是保留字。
用法:

time sleep 5

输出类似:

0.0u 0.0s 0:05 0% 0+0k 0+0io 0pf+0w

其中 0:05 就是 分:秒 格式,即 ?:? 样式。
这串数字的含义:

部分含义
%Uu用户态 CPU 秒数
%Ss内核态 CPU 秒数
%E实际经过时间,格式 h:mm:ss 或 m:ss
%PCPU 占用百分比
%X+%Dk内存占用
%I+%OioIO 次数
%Fpf+%Ww缺页/换出

1. 自定义格式:set time 变量

csh 用 time 变量控制输出格式。
可以设置成格式字符串:

set time = "%Uu %Ss %E %P"
time sleep 5

输出:

0.0u 0.0s 0:05 0%

也可以设置成 (秒数 格式字符串),实现 超过指定 CPU 秒数才自动打印:

set time = ( 2 "%Uu %Ss %E %P" )
# 之后运行超过 2 秒 CPU 时间的命令会自动输出计时

2. 输出 ?m?s 样式

csh 的 %E 默认输出 ?:?(如 0:05、1:05),而不是 1m5s。
如果非要 1m5s,需要自己后处理。例如:

set start = `date +%s`
sleep 65
set end = `date +%s`
@ total = $end - $start
@ minutes = $total / 60
@ seconds = $total % 60
echo "耗时 ${minutes}m${seconds}s"

输出:

耗时 1m5s

注意:csh 的 @ 是算术运算,$total 必须是整数。


三、处理 VCS 日志中的 CPU Time

仿真工具 VCS 的日志末尾通常有:

CPU Time:    420.930 seconds;       Data structure size:   0.4Mb

这个格式是固定的,VCS 没有选项改成“几分几秒”。
但我们可以用脚本后处理。

Bash 后处理:输出 ?m?s

grep "CPU Time" simv.log | awk -F'[:;]' '{
    cpu_sec = $2 + 0;
    minutes = int(cpu_sec / 60);
    seconds = cpu_sec - minutes * 60;
    printf "CPU Time: %dm%.3fs\n", minutes, seconds;
}'

输出:

CPU Time: 7m0.930s

Bash 后处理:输出 ?:?

grep "CPU Time" simv.log | awk -F'[:;]' '{
    cpu_sec = $2 + 0;
    minutes = int(cpu_sec / 60);
    seconds = cpu_sec - minutes * 60;
    printf "CPU Time: %d:%05.2f\n", minutes, seconds;
}'

输出:

CPU Time: 7:00.93

csh 后处理

set cpu_sec = `grep "CPU Time" simv.log | awk -F'[:;]' '{print $2+0}'`
if ("$cpu_sec" != "") then
    @ minutes = $cpu_sec / 60
    @ seconds = $cpu_sec % 60
    echo "CPU Time: ${minutes}m${seconds}s"
endif

四、总结与推荐

需求Bashcsh / tcsh
基本计时time commandtime command
自定义格式TIMEFORMATset time = "格式"
输出 ?m?sTIMEFORMAT='%0lR' 得到 1m5s需自己算,%E 是 1:05
输出 ?:?需自己算(SECONDS / EPOCHREALTIME)%E 默认就是 1:05
计时管道/复合命令支持,用 {} 或 ()只支持简单命令
输出目的地stderrstdout
超时自动打印不支持set time = ( 秒数 "格式" )

推荐:

  • 日常用 Bash:TIMEFORMAT='耗时 %0lR',直接得到 1m5s,简洁明了。

  • 如果习惯 分:秒:Bash 里用 SECONDS 自己算,csh 里直接用 %E。

  • 处理 VCS 日志:用 awk 提取秒数并转换,灵活可控。

  • 长时间命令:优先用 ?m?s 或 ?:?,比纯秒数(如 420.930 seconds)直观得多。

希望这篇总结能帮你在不同 Shell 下都能轻松读出命令的真实耗时。

感谢阅读,更多文章点击这里:【专栏:ExASIC】
公众号:ExASIC
分享数字集成电路设计中的经验和方法。分享让工作更轻松。
公众号二维码
留言(0)
还没有留言,来说两句吧。
留言需要 登录 或 注册(注册后需通过邮箱验证)。
相关文章