`time`如何通过管道控制其他进程?

How can `time` control other processes through a pipe?

在一般情况下,我们有一个像 P | Q | R 这样的命令,它对 shell 具有以下语义:

这非常清晰。但是让我们观察以下几点:

$ time echo lol | cat | wc -l
echo lol  0.00s user 0.00s system 10% cpu 0.005 total
cat  0.00s user 0.00s system 81% cpu 0.001 total
wc -l  0.00s user 0.00s system 83% cpu 0.001 total

这里我们有时间工作,因为它完全了解管道中的所有内容,而从语法的角度来看,我希望它只知道 echo lol,它将被启动——我猜——作为子进程。

如果 time 是一个 shell 内置函数,这将很容易完成,但事实并非如此,至少在我的 GNU/Linux 操作系统上:which time 给出我 /usr/bin/time,并且 bash 联机帮助页没有提到 time 内置函数。

我想不出任何其他具有类似特征的程序。 time 程序是否有特殊例外或允许这种交互的非常晦涩的系统调用?

您为 time echo lol | cat | wc -l 显示的输出确实需要 time 成为 shell 内置函数(实际上比 shell 内置函数更罕见:关键字, 比如 iffor.)

您的调查存在一些缺陷。首先,您不清楚 shell 您使用的是什么。您示例中 time 输出的具体格式是由 zsh 生成的,它有一个 time 关键字。它记录在 zshmisc(1).

bash 也有一个 time 关键字,但它不会为管道中的每个命令生成单独的输出。在 bash 手册页中很难找到,因为他们忽略了将其列在其他关键字中,但在标题 "SHELL GRAMMAR"、副标题 "Pipelines":

下进行了解释

If the time reserved word precedes a pipeline, the elapsed as well as user and system time consumed by its execution are reported when the pipeline terminates. The -p option changes the output format to that specified by POSIX. The TIMEFORMAT variable may be set to a format string that specifies how the timing information should be displayed; see the description of TIMEFORMAT under Shell Variables below.

你的另一个错误是使用 which,你显然在 bash 中使用了 运行 你在 zsh 中的示例 time 命令之后。在 zsh 中有一个内置 which 可以告诉你其他内置。在 bash 中没有。所以你 运行 一个外部命令 which 无法知道你的 shell 中内置了什么;它只能告诉您它在 $PATH.

中找到的 time

有一些与 which 相关的 zsh 内置函数;我喜欢 where 命令,它列出 所有 找到命令的位置,而不仅仅是当前搜索顺序中第一个的位置。在 bash 中,您应该使用 type 命令来查明某些内容是否是内置的。

bash$ type time
time is a shell keyword
zsh% where time
time: shell reserved word
/usr/bin/time

注意: 此答案基于 bash 4.1.17 和 zsh 5.0.6,我可以轻松测试这些版本。如果有某个版本的 bash 复制了 zsh time 格式,答案会更可信,但据我所知还不存在。