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

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


当前回答

要逐行测量delta,请尝试用指针测量。

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

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

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

其他回答

使用内置的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

perf stat Linux命令行实用程序

这个工具对于获取时间来说是多余的。但是它可以为您做更多的事情,帮助您分析和修复速度慢,这是值得了解的。Ubuntu 22.04安装:

sudo apt install linux-tools-common linux-tools-generic
echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid

用法:

perf stat <mycmd>

使用stress-ng运行示例:

perf stat stress-ng --cpu 1 --cpu-method matrixprod -t 5

样例输出:

 Performance counter stats for 'stress-ng --cpu 1 --cpu-method matrixprod -t 5':

          5,005.46 msec task-clock                #    0.999 CPUs utilized          
                88      context-switches          #   17.581 /sec                   
                 1      cpu-migrations            #    0.200 /sec                   
             1,188      page-faults               #  237.341 /sec                   
    18,847,667,167      cycles                    #    3.765 GHz                    
    26,544,261,897      instructions              #    1.41  insn per cycle         
     3,239,655,001      branches                  #  647.225 M/sec                  
        25,393,369      branch-misses             #    0.78% of all branches        

       5.012218939 seconds time elapsed

       4.998051000 seconds user
       0.009122000 seconds sys

perf还可以做一些更高级的事情,例如,在这里我将展示如何使用它来分析代码:我如何分析运行在Linux上的c++代码?

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

编者按: 为了确保您调用的是外部实用程序time而不是shell的time关键字,请以/usr/bin/time来调用它 time是posix强制的实用程序,但它需要支持的唯一选项是-p。 特定的平台实现特定的、非标准的扩展:-v与GNU的time实用程序一起工作,如下所示(问题被标记为linux);BSD/macOS实现使用-l来产生类似的输出-参见man 1次。

详细输出示例:

$ /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

如果您想要更精确,请使用%N和date(并使用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

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

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

上面的命令将导致shell提示符更改为:

[HH:MM:SS username@hostname]$ 

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

notes: 1) beware that if you waited for sometime before you type your next command, then this time need to be considered, i.e the time displayed in the shell prompt is the timestamp when the shell prompt was displayed, not when you enter command. some users choose to hit Enter key to get a new prompt with a new timestamp before they are ready for the next command. 2) There are other available options and modifiers that can be used to change the bash prompt, refer to ( man bash ) for more details.