有没有办法找到shell中最后执行的命令的运行时间?

Lam*_*bda 24 unix linux macos bash shell

是否有这样的命令time可以显示shell上最后或过去执行的命令的运行时间细节?

ZyX*_*ZyX 13

我不知道,它是如何在bash中,但在zsh中你可以定义preexecprecmd函数,以便它们将当前时间保存到变量$STARTTIME(preexec)和$ENDTIME(precmd),这样你就能找到大致的运行时间.或者您可以定义一个accept-line函数,以便它time在每个命令之前添加.

更新:这是代码,它将在$_elapsed数组中存储已用时间:

preexec () {
   (( $#_elapsed > 1000 )) && set -A _elapsed $_elapsed[-1000,-1]
   typeset -ig _start=SECONDS
}
precmd() { set -A _elapsed $_elapsed $(( SECONDS-_start )) }
Run Code Online (Sandbox Code Playgroud)

然后,如果你运行sleep 10s:

% set -A _elapsed # Clear the times
% sleep 10s
% sleep 2s ; echo $_elapsed[-1]
10
% echo $_elapsed
0 10 0
Run Code Online (Sandbox Code Playgroud)

不需要四个变量.名称或额外延迟没有问题.请注意,$_elapsed数组可能会变得非常大,因此您需要删除第一项(这是通过以下代码完成的:) (( $#_elapsed > 1000 )) && set -A _elapsed $_elapsed[-1000,-1].

UPDATE2:发现脚本在bash中支持zsh样式的precmd和preexec.也许你将需要删除typeset -ig(我只是用来强制$_start是整数),更换set -A var ...var=( ... )为了得到这个工作.我不知道如何切割数组并在bash中获取它们的长度.

脚本:http://www.twistedmatrix.com/users/glyph/preexec.bash.txt

UPDATE3:发现一个问题:如果你用空行命中返回preexec不运行,而precmd则运行,所以你将在$_elapsed数组中得到无意义的值.为了解决此问题precmd,请使用以下代码替换该函数:

precmd () {
   (( _start >= 0 )) && set -A _elapsed $_elapsed $(( SECONDS-_start ))
   _start=-1 
}
Run Code Online (Sandbox Code Playgroud)

  • 也许你可以将你的脚本与`EXTENDED_HISTORY`选项结合起来以提高稳健性?只是扔了一个阿达.我没有超过10个想法,这是我的睡眠时间(等待脚本完成其工作). (2认同)

Att*_*igh 12

自从其他人回答了这些问题后,世界可能会发生一些变化。

zsh 有一些内置功能来计算命令需要多长时间。

如果您启用 inc_append_history_time 选项

setopt inc_append_history_time

然后运行每个命令所花费的时间会保存在您的历史记录中,然后可以使用history -D.


Jos*_*vin 6

我认为您正在运行需要很长时间的命令,并且一开始没有意识到您想要计算它们需要多长时间才能完成。在 zsh 中,如果将环境变量 REPORTTIME 设置为一个数字,则任何花费超过该秒数的命令都会打印出它所花费的时间,就像您在其前面使用 time 命令运行它一样。您可以在 .zshrc 中设置它,以便长时间运行的命令将始终打印其时间。请注意,睡眠时间(与用户/系统时间相反)不计入触发计时器的时间,但仍会被跟踪。


Pau*_*ce. 5

编辑3:

这个答案的结构:

  1. 没有现成的方法来为已经运行的命令计时
  2. 有一些方法可以推断出对命令运行时间的估计.
  3. 显示了概念证明(从假设不能完成并以假设错误的结论开始).
  4. 您可以预先设置黑客,记录您运行的每个命令的已用时间
  5. 结论

根据上述大纲,其部分标注的答案如下:

第1部分 - 简短的回答是"不"

原版的

不,谢谢.你必须使用time.

第2部分 - 也许你可以推断出一个结果

在某些情况下,如果程序将输出文件或信息写入日志文件,您可能会推断出运行时间,但这可能是特定于程序的,只是猜测.如果在Bash中设置了HISTTIMEFORMAT,则可以查看历史文件中的条目,以了解程序何时启动.但是没有记录结束时间,因此如果在您感兴趣的程序完成后立即启动另一个程序,则只能推断出一个持续时间.

第3部分 - 假设是伪造的

假设:空闲时间将计入经过的时间

编辑:

这是一个说明我的观点的例子.它基于ZyX的建议,但使用其他方法也是类似的.

zsh:

% precmd() { prevstart=start; start=$SECONDS; }
% preexec() { prevend=$end; end=$SECONDS; }
% echo "T: $SECONDS ps: $prevstart pe: $prevend s: $start e: $end"
T: 1491 ps: 1456 pe: 1458 s: 1459 e: 1491
Run Code Online (Sandbox Code Playgroud)

现在我们等待...让我们说15秒,然后:

% echo "T: $SECONDS"; sleep 10
T: 1506
Run Code Online (Sandbox Code Playgroud)

现在我们等待......让我们说20秒,然后:

% echo "T: $SECONDS ps: $prevstart pe: $prevend s: $start e: $end"
T: 1536 ps: 1492 pe: 1506 s: 1516 e: 1536
Run Code Online (Sandbox Code Playgroud)

如你所见,我错了.开始时间(1516)减去前一结束时间(1506)命令(sleep 10)的持续时间.这也表明我在函数中使用的变量需要更好的名称.

假设伪造 -这可能得到正确经过时间不包括空闲时间

第4部分 - 记录每个命令的经过时间的黑客攻击

编辑2:

以下是ZyX答案中函数的Bash等价物(它们需要链接到那里的脚本):

preexec () {
   (( ${#_elapsed[@]} > 1000 )) && _elapsed=(${_elapsed[@]: -1000})
   _start=$SECONDS
}

precmd () {
   (( _start >= 0 )) && _elapsed+=($(( SECONDS-_start )))
   _start=-1 
}
Run Code Online (Sandbox Code Playgroud)

安装preexec.bash(从链接脚本)并创建上面的两个函数后,示例运行将如下所示:

$ _elapsed=() # Clear the times
$ sleep 10s
$ sleep 2s ; echo ${_elapsed[@]: -1}
10
$ echo ${_elapsed[@]}
0 10 2
Run Code Online (Sandbox Code Playgroud)

第5部分 - 结论

使用time.