使用 unix "time" 命令将时间输出到文件,但将命令输出保留到控制台

Output time to file with unix "time" command, but leave output of command to console

我对有一些输出的命令计时。我想从 time 命令输出实时到一个文件,但是把命令的输出留在控制台。

例如,如果我这样做 time my_command 我会在控制台中打印出来

several lines of output from my_command ... 
real 1m25.970s
user 0m0.427s
sys 0m0.518s

在这种情况下,我只想将 1m25.970s 存储到文件中,但仍将命令的输出打印到控制台。

time 命令很棘手。 time 的 POSIX 规范 没有定义默认输出格式,但确实为 -p(大概是 'POSIX')选项定义了格式。请注意管道中命令序列的(不容易理解的)讨论。

Bash 规范说 time 前缀为 'pipeline',这意味着 time cmd1 | cmd2 乘以 cmd1cmd2。它将结果写入标准错误。科恩 shell 相似。

POSIX格式要求在real等标签和时间之间有一个space;默认格式通常使用制表符而不是 space。请注意,/usr/bin/time 命令可能还有另一种输出格式。它在 macOS 上做的,例如,单行列出 3 次,默认情况下,标签在时间值之后;它支持 -p 以近似 POSIX 格式打印(但它在标签和时间之间有多个 spaces)。

您可以轻松地将写入标准错误的所有信息放入文件中:

(time my_command) 2> log.file

如果 my_command 或它调用的任何程序向标准错误报告任何错误,这些错误也会进入日志文件。您将把 time 的所有三行输出写入文件。

如果您的 shell 是 Bash,您可以使用 process substitution 过滤一些输出。

我不会尝试使用单个命令行;使其工作所需的象形文字非常可怕,最好封装在 shell 脚本中。

例如,shell 脚本 time.filter 捕获 time 的输出并仅将 real 时间写入日志文件(默认 log.file,可通过提供替代日志文件名作为第一个参数进行配置

#!/bin/sh

output="${1:-log.file}"
shift
sed -E '/^real[[:space:]]+(([0-9]+m)?[0-9]+[.][0-9]+s?)/{ s///; w '"$output"'
        d;}
        /^(user|sys)[[:space:]]+(([0-9]+m)?[0-9]+[.][0-9]+s?)/d' "$@"

这假设您的 sed 使用 -E 来启用扩展的正则表达式。 脚本的第一行查找包含 real 标签及其后的时间的行(有多种可能的格式——但不是全部)。它接受一个可选的分钟值,例如 60m05.003s,或者只是一个秒值 5.00s,或者只是 5.0(POSIX 格式——小数点后至少需要一位数字).它捕获时间部分并将其打印到所选文件(默认情况下,log.file;您可以指定一个替代名称作为命令行上的第一个参数)。请注意,即使是 GNU sed 也将 w 命令之后的所有内容都视为文件名;您必须在换行符上继续 d(删除)命令和右括号 }。 GNU sed 不需要 d 后的分号; BSD (macOS) sed 可以。第二行识别并删除报告中 usersys 次的行。其他所有内容均保持不变。

该脚本处理您在日志文件名之后提供的任何文件,或者如果您提供 none 则处理标准输入。更好的命令行表示法将使用显式选项 (-l logfile) 和 getopts 来指定日志文件。

有了它,我们可以设计一个程序来报告标准错误和标准输出 — my_command:

echo "nonsense: error: positive numbers are required for argument 1" >&2
dribbler -s 0.4 -r 0.1 -i data -t
echo "apoplexy: unforeseen problems induced temporary amnesia" >&2

您可以使用 cat data 而不是 dribbler 命令。如图所示,dribbler 命令从 data 中读取行,将它们写入标准输出,并在行之间具有随机延迟和高斯分布。平均延迟为0.4秒;标准偏差为 0.1 秒。另外两行伪装成向标准错误报告错误的命令。

我的 data 文件包含一个名为 'The Great Panjandrum'.

的废话 'poem'

有了这个背景,我们可以 运行 命令并在 log.file 中捕获实时时间,删除(忽略)用户和系统时间值,同时发送其余的标准错误到标准错误通过使用:

$ (time my_command) 2> >(tee raw.stderr | time.filter >&2)
nonsense: error: positive numbers are required for argument 1
So she went into the garden
to cut a cabbage-leaf
to make an apple-pie
and at the same time
a great she-bear coming down the street
pops its head into the shop
What no soap
So he died
and she very imprudently married the Barber
and there were present
the Picninnies
and the Joblillies
and the Garyulies
and the great Panjandrum himself
with the little round button at top
and they all fell to playing the game of catch-as-catch-can
till the gunpowder ran out at the heels of their boots
apoplexy: unforeseen problems induced temporary amnesia

$ cat log.file
0m7.278s
$

(所用时间通常在 6 到 8 秒之间。共有 17 行,因此您预计每行 0.4 秒大约需要 6.8 秒。)空行来自 time ;很难删除那个空行,而且只有那个空行,特别是 POSIX 说它是可选的。不值得。