我想要time
一个命令,该命令由两个单独的命令组成,一个管道输出到另一个管道。例如,考虑以下两个脚本:
$ cat foo.sh
#!/bin/sh
sleep 4
$ cat bar.sh
#!/bin/sh
sleep 2
现在,我如何才能time
报告所花费的时间foo.sh | bar.sh
(是的,我知道这里的管道没有意义,但这只是一个示例)?如果我在不使用管道的子外壳中依次运行它们,则可以正常工作:
$ time ( foo.sh; bar.sh )
real 0m6.020s
user 0m0.010s
sys 0m0.003s
但是在管道传输时我无法使其工作:
$ time ( foo.sh | bar.sh )
real 0m4.009s
user 0m0.007s
sys 0m0.003s
$ time ( { foo.sh | bar.sh; } )
real 0m4.008s
user 0m0.007s
sys 0m0.000s
$ time sh -c "foo.sh | bar.sh "
real 0m4.006s
user 0m0.000s
sys 0m0.000s
我已经阅读了一个类似的问题(如何在多个命令上运行时间并将时间输出写入文件?),还尝试了独立time
可执行文件:
$ /usr/bin/time -p sh -c "foo.sh | bar.sh"
real 4.01
user 0.00
sys 0.00
如果我创建仅运行管道的第三个脚本,它甚至不起作用:
$ cat baz.sh
#!/bin/sh
foo.sh | bar.sh
然后时间:
$ time baz.sh
real 0m4.009s
user 0m0.003s
sys 0m0.000s
有趣的是,它看起来好像没有time
在第一个命令完成后就退出。如果我更改bar.sh
为:
#!/bin/sh
sleep 2
seq 1 5
再time
一次,我期望time
输出在之前打印,seq
但不是:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
看起来time
并没有计算执行时间,bar.sh
尽管在打印报告1之前等待它完成。
所有测试均在Arch系统上运行,并使用bash 4.4.12(1)-release。我只能将bash用于该项目的一部分,所以即使zsh
有其他功能强大的shell可以解决它,这对我也不是可行的解决方案。
那么,如何获得一组管道命令运行所需的时间?而且,当我们使用它时,为什么它不起作用?它看起来像time
马上就第一个命令完成退出。为什么?
我知道我可以通过以下方式获得个人时间:
( time foo.sh ) 2>foo.time | ( time bar.sh ) 2> bar.time
但是我仍然想知道是否有可能将整个事情作为一个单一的操作进行计时。
1 这似乎不是缓冲区问题,我尝试使用unbuffered
和运行脚本,并且stdbuf -i0 -o0 -e0
仍然在time
输出之前打印数字。