我把这个当作谜题,想展示我的困惑结果:
首先我摆弄了时间测量。 date +%s.%N(我之前没有意识到)是我开始的地方。不幸的是,bashs 算术评估似乎不支持浮点数。因此,我选择了其他东西:
$ 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。
$ 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
$
该死!我再次陷入子外壳问题。为了解决这个问题,我定义了另一个变量:
$ 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 一起解决这个问题。在一个类似的谜题(SO: How to change bash prompt color based on exit code of last command?)中,我已经掌握了“引用地狱”。因此,我应该可以再做一次:
$ 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,这似乎是正确的,并且我过去已经将其用于其他一些个人定制。
所以,把它们放在一起 - 这些是我添加到我的 ~/.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"
添加了第 3 行(date 命令)以解决另一个问题。将其注释掉并启动一个新的交互式 bash 以找出原因。
我的 cygwin xterm 与 bash 的快照,我将以上行添加到 ./~bashrc:
注意事项:
我认为这是解决难题的方法,而不是“非常有成效”的解决方案。我敢肯定,这种时间测量会消耗大量时间。 time 命令可能会提供更好的解决方案:SE: How to get execution time of a script effectively?。但是,这是练习 bash 的好讲座……
不要忘记,此代码污染了您的/tmp 目录,其中包含越来越多的小文件。不时清理/tmp,或添加适当的清理命令(例如~/.bash_logout)。