我有以下示例脚本:
#!/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