在bash中,time
构造的输出转到其标准错误,您可以重定向它影响的管道的标准错误。因此,让我们从写入其输出和错误流as的命令开始:sh -c 'echo out; echo 1>&2 err'
。为了不使命令的错误流与的输出混淆time
,我们可以暂时将命令的错误流转移到其他文件描述符:
{ time -p sh -c 'echo out; echo 1>&2 err' 2>&3; }
这将写入out
fd 1,err
fd 3和时间fd 2:
{ time -p sh -c 'echo out; echo 1>&2 err' 2>&3; } \
3> >(sed 's/^/ERR:/') 2> >(sed 's/^/TIME:/') > >(sed 's/^/OUT:/')
err
在fd 2上拥有时间,在fd 3上拥有时间会更令人愉快,因此我们交换它们,这很麻烦,因为没有直接的方法可以交换两个文件描述符:
{ { { time -p sh -c 'echo out; echo 1>&2 err' 2>&3; } 3>&2 2>&4; } 4>&3; } 3> >(sed 's/^/TIME:/') 2> >(sed 's/^/ERR:/') > >(sed 's/^/OUT:/')
这显示了如何对命令的输出进行后处理,但是如果要同时捕获命令的输出及其时间,则需要更加努力。使用临时文件是一种解决方案。实际上,如果您需要同时捕获命令的标准错误及其标准输出,则这是唯一可靠的解决方案。但是否则,您可以捕获整个输出并利用time
具有可预测格式的事实(如果time -p
用于获取POSIX格式或bash特定TIMEFORMAT
变量)。
nl=$'\n'
output=$(TIMEFORMAT='%R %U %S %P'; mycommand)
set ${output##*$nl}; real_time=$1 user_time=$2 system_time=$3 cpu_percent=$4
output=${output%$nl*}
如果您只关心挂钟时间,那么在date
之前和之后运行是一个简单的解决方案(如果由于加载外部命令花费了额外的时间而更加不精确)。
fork()
,execvp()
和wait3()/wait4()
。最终,这就是时间和朋友在做什么。我不知道在不重定向到文件或类似方法的情况下在bash / perl中执行类似操作的方法。