问题描述
通过执行PS0和PS1变量中的代码(据我所知,在运行提示命令之前和之后评估),应该可以记录每个正在运行的命令的时间并将其显示在提示中.像这样的东西:
It seems that by executing code in PS0 and PS1 variables (which are eval'ed before and after a prompt command is run, as I understand) it should be possible to record time of each running command and display it in the prompt. Something like that:
user@machine ~/tmp
$ sleep 1
user@machine ~/tmp 1.01s
$
但是,由于这样的事情不起作用,我很快就陷入了PS0中的录制时间:
However, I quickly got stuck with recording time in PS0, since something like this doesn't work:
PS0='$(START=$(date +%s.%N))'
据我了解,START
分配发生在子外壳中,因此在外壳中不可见.您将如何处理?
As I understand, START
assignment happens in a sub-shell, so it is not visible in the outer shell. How would you approach this?
推荐答案
我把这当作难题,并想显示我困惑的结果:
I took this as puzzle and want to show the result of my puzzling:
首先,我摆弄时间测量. date +%s.%N
(我以前没有意识到)是我从那里开始的.不幸的是,似乎bash
的算术评估似乎不支持浮点数.因此,我选择了其他东西:
First I fiddled with time measurement. The date +%s.%N
(which I didn't realize before) was where I started from. Unfortunately, it seems that bash
s arithmetic evaluation seems not to support floating points. Thus, I chosed something else:
$ START=$(date +%s.%N)
$ awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$START') }' /dev/null
8.059526s
$
这足以计算时间差.
接下来,我确认了您已经描述的内容:子Shell调用阻止使用Shell变量.因此,我考虑了在哪里还可以存储开始时间,该时间对于子Shell来说是全局的,但是对于本地而言,足以在多个交互式Shell中同时使用.我的解决方案是临时的.文件(在/tmp
中).为了提供唯一的名称,我想出了以下模式:/tmp/$USER.START.$BASHPID
.
Next, I confirmed what you already described: sub-shell invocation prevents usage of shell variables. Thus, I thought about where else I could store the start time which is global for sub-shells but local enough to be used in multiple interactive shells concurrently. My solution are temp. files (in /tmp
). To provide a unique name I came up with this pattern: /tmp/$USER.START.$BASHPID
.
$ date +%s.%N >/tmp/$USER.START.$BASHPID ; \
> awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$(cat /tmp/$USER.START.$BASHPID)') }' /dev/null
cat: /tmp/ds32737.START.11756: No such file or directory
awk: cmd. line:1: BEGIN { printf("%fs", 1491297723.111219300 - ) }
awk: cmd. line:1: ^ syntax error
$
该死!再次,我陷入了子外壳问题.为了解决这个问题,我定义了另一个变量:
Damn! Again I'm trapped in the sub-shell issue. To come around this, I defined another variable:
$ INTERACTIVE_BASHPID=$BASHPID
$ date +%s.%N >/tmp/$USER.START.$INTERACTIVE_BASHPID ; \
> awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)') }' /dev/null
0.075319s
$
下一步:将其与PS0
和PS1
一起摆弄.在类似的难题中(),我已经掌握了引用地狱"的知识.因此,我应该能够再次执行此操作:
Next step: fiddle this together with PS0
and PS1
. In a similar puzzle (SO: How to change bash prompt color based on exit code of last command?), I already mastered the "quoting hell". Thus, I should be able to do it again:
$ PS0='$(date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}")'
$ PS1='$(awk "BEGIN { printf(\"%fs\", "$(date +%s.%N)" - "$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)") }" /dev/null)'"$PS1"
0.118550s
$
啊.它开始工作.因此,只有一个问题-为INTERACTIVE_BASHPID
的初始化找到正确的启动脚本.我发现~/.bashrc
似乎是正确的选择,并且我过去已将其用于其他一些个人定制.
Ahh. It starts to work. Thus, there is only one issue - to find the right start-up script for the initialization of INTERACTIVE_BASHPID
. I found ~/.bashrc
which seems to be the right one for this, and which I already used in the past for some other personal customizations.
因此,将它们放在一起-这些是我添加到~/.bashrc
的行:
So, putting it all together - these are the lines I added to my ~/.bashrc
:
# command duration puzzle
INTERACTIVE_BASHPID=$BASHPID
date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}"
PS0='$(date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}")'
PS1='$(awk "BEGIN { printf(\"%fs\", "$(date +%s.%N)" - "$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)") }" /dev/null)'"$PS1"
已添加第三行(date
命令)来解决另一个问题.将其注释掉并开始进行新的交互式bash找出原因.
The 3rd line (the date
command) has been added to solve another issue. Comment it out and start a new interactive bash to find out why.
使用bash的cygwin xterm的快照,在其中我将以上几行添加到了./~bashrc
:
A snapshot of my cygwin xterm with bash where I added the above lines to ./~bashrc
:
注意:
-
我认为这是对难题的解决方案,而不是严重的生产性"解决方案.我敢肯定,这种时间测量会消耗很多时间.
time
命令可能提供更好的解决方案: SE :如何有效地获得脚本的执行时间?.但是,这是练习bash的不错的演讲...
I consider this rather as solution to a puzzle than a "serious productive" solution. I'm sure that this kind of time measurement consumes itself a lot of time. The
time
command might provide a better solution: SE: How to get execution time of a script effectively?. However, this was a nice lecture for practicing the bash...
不要忘记此代码会污染越来越多的小文件,从而污染您的/tmp
目录.
Don't forget that this code pollutes your /tmp
directory with a growing number of small files. Either clean-up the /tmp
from time to time or add the appropriate commands for clean-up (e.g. to ~/.bash_logout
).
这篇关于使用PS0和PS1显示每个bash命令的执行时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!