我有一个bash脚本,叫它Exp,它执行一个计算实验,我想有
的结果time Exp
首先,它需要总是完成(并依赖于输入"time Exp")。还不够——对于您(或用户!!)需要它的关键情况,它将是忘记了),其次,脚本Exp本身需要将其存储在一个文件中。
编写一个包装器脚本(调用"time Exp")似乎使普通的工作与由于时间命令破坏了参数和输入/输出,Exp不可能。
但是实际上我们所需要的只是访问这个全域的Exp中的数据记录(也可以通过ps访问),它只是按时间打印!这就是为什么我要求一个"优雅"的解决方案,而不仅仅是先以某种方式存储日期在Exp中,最后,在退出之前,计算差值。只是模拟一下时间命令在Exp中所做的事情。我认为它在其他很多地方都很有用情况。
由于POSIX定义了时间实用程序来根据标准错误编写结果,因此您必须注意的唯一技巧是bash
内置time
的行为略有不同。
$ time sleep 1
real 0m1.004s
user 0m0.001s
sys 0m0.002s
$ time sleep 1 2>xyz
real 0m1.005s
user 0m0.001s
sys 0m0.003s
$ (time sleep 1) 2>xyz
$ cat xyz
real 0m1.005s
user 0m0.001s
sys 0m0.002s
$ /usr/bin/time sleep 1 2>xyz
$ cat xyz
1.00 real 0.00 user 0.00 sys
$
在MacOS X 10.7上显示的测试。time
命令的内置版本和外部版本的输出格式不同。还请注意,在子shell格式中,内置time
通常被重定向,但在简单的情况下,在内置time
之后重定向输出不会将输出发送到标准错误的其余部分到达的相同位置。
因此,这些观察结果允许您编写优雅的脚本。可能最简单的方法是将现有的脚本包装为函数,然后通过内置的time
调用该函数。
# This is what was in the Exp script before.
# It echoes its name and its arguments to both stdout and stderr
echo "Exp $*"
echo "Exp $*" 1>&2
修改脚本log=./Exp.log
Exp()
{
# This is what was in the Exp script before.
# It echoes its name and its arguments to both stdout and stderr
echo "Exp $*"
echo "Exp $*" 1>&2
}
(time Exp "$@") 2>> $log
请注意,在调用Exp
函数时小心地使用了"$@"
,以保留在命令行上传递的单独参数,而在函数内部同样小心地使用了$*
(它失去了单独的参数,但只是为了说明目的)。
唯一的问题是,原始命令的错误输出也会作为计时信息进入相同的日志文件。这是可以解决的,但涉及棘手的多重重定向,更有可能混淆而不是帮助。但是,需要说明的是,这可以很好地工作:
log=./Exp.log
Exp()
{
# This is what was in the Exp script before.
# It echoes its name and its arguments to both stdout and stderr
echo "Exp $*"
echo "Exp $*" 1>&2
}
exec 3>&2
(time Exp "$@" 2>&3 ) 2>> $log
您可以添加以下内容作为脚本的第一行:
<>之前test -z "$TIMED" && TIMED=yes执行时间$0 $@之前如果在环境中设置了TIMED,则不会运行如果你想的话,它提供了一种方法来抑制计时
上述两种解决方案调用time命令。我怀疑即使是非常@Jonathan Leffler精心制作的一个在功能上与原始脚本相当:它似乎关心输出到标准输出和标准误差,但如何它表现出需要测试的W.R.T.符号链接(这不会那么简单——)关于路径有很多微妙之处,特别是当包含链接时。我认为w.r.t.肮脏的引用绝对会改变语义对于原始脚本,有必要在参数中再添加一个引号层(例如,如果脚本远程运行,则需要使用引号)。
有了这两个问题,处理路径、符号链接和引用,我们有过去有很多麻烦,而且这些错误很难被发现:通常是我们编写的脚本使用了来自许多数学/计算机科学软件包的复杂脚本,其中必须处理数百个特别安装的软件包,每个都有自己奇怪的特点,所以我们要尽量避免增加了更多的并发症
我在@Arne的帮助下找到的解决方案更简单;看到如何使用S-output-modifier与Unix/Linux命令ps?
只需要加上
一行ps p $$ k time S | tail -n 1 | tr -s '[:space:]' | cut -d ' ' -f 4 > log-file
当想要在日志文件中存储(总)进程时间时,将添加到脚本中。不知道时间命令从哪里得到的挂钟和系统时间,但是对于挂钟,也许需要做时间的减法;我不知道关于系统时间,但它一定在某个地方。