首页 > 解决方案 > 使用 unix "time" 命令将时间输出到文件,但将命令的输出留给控制台

问题描述

我为一个有一些输出的命令计时。我想将 time 命令的实时时间输出到文件,但将命令的输出留给控制台。

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

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

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

标签: shellunixtimeio-redirection

解决方案


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

Bash 规范说time前缀是'pipeline',这意味着time cmd1 | cmd2同时cmd1cmd2. 它将结果写入标准错误。Korn shell 是类似的。

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

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

(time my_command) 2> log.file

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

如果你的 shell 是 Bash,你可以使用进程替换来过滤一些输出。

我不会用一个命令行来尝试它。使它工作所需的象形文字是可怕的,最好封装在 shell 脚本中。

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

#!/bin/sh

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

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

该脚本会处理您在日志文件名之后提供的任何文件,如果您没有提供,则处理标准输入。更好的命令行表示法将使用显式选项 ( -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”

有了这个背景,我们可以运行命令并捕获实时时间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 说它是可选的。这不值得。


推荐阅读