为什么内置时间在管道中不起作用?

为什么内置时间在管道中不起作用?

我有以下示例脚本:

#!/usr/bin/env bash
sleep 5
printf "times cmd: "
times
printf "pipeline: "
times | ( read user sys; echo $user; )
printf "head: "
times | head -n1
printf "times cmd again: "
times

输出如下:

$ ./test.sh 
times cmd: 0m0.003s 0m0.005s
0m0.001s 0m0.001s
pipeline: 0m0.000s
head: 0m0.000s 0m0.000s
times cmd again: 0m0.003s 0m0.006s
0m0.003s 0m0.004s

问题是,为什么times命令在与管道一起使用时会重置时间?有什么办法可以避免它来解析该值吗?

答案1

在管道中,所有命令都在子 shell 中运行。times报告 shell 及其子 shell 所花费的时间,但不报告其父 shell 所花费的时间。

您可以尝试进程替换:

times > >( head -n1 )
times > >( read user sys ; echo $user )

答案2

这是我们谈论哪个外壳的问题。
在这个外壳上,我得到:

$ times
0m9.805s 0m3.372s
39m29.072s 0m15.537s

因为它已经运行了一段时间了。
然而,子 shell 将报告零:

$ ( times )
0m0.000s 0m0.000s
0m0.000s 0m0.000s

并且,当管道的每个部分在子 shell 中执行时:

$  sleep 10 | times
0m0.000s 0m0.000s
0m0.000s 0m0.000s

如果运行上面的命令,您应该times立即看到输出(因为它不依赖于管道),并且 shell 提示符会在 10 秒后返回。

解决方法?

留在“这个”外壳中:

$ times > >(read user sys; echo "$user") 

那么,为什么需要时间呢?time或者更强大的功能可以/usr/bin/time为您工作吗?

使用时间:

$ TIMEFORMAT="%R;%U;%S"; time { sleep 1; }
1.001;0.000;0.000
$ TIMEFORMAT="%U"; time { sleep 1; }         #### If you only want user.
0.000

将多个进程括在大括号中:

$ time { wc /etc/hosts; sleep 2; }
 21 115 327 /etc/hosts

real    0m2.003s
user    0m0.000s
sys     0m0.000s

使用更强大的外部time(遗憾的是它只适用于外部可执行文件):

$ /usr/bin/time wc /etc/hosts
 21 115 327 /etc/hosts
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata 534maxresident)k
0inputs+0outputs (0major+109minor)pagefaults 0swaps

相关内容