$ time (exec -a foo echo hello)
hello
似乎stderr(在哪里time写入其输出)在某处泄漏;显然这不是我的本意。
我的问题可以笼统地表述为“当子shell 执行另一个程序时,为什么终端上没有写入标准错误流? ”。
几点注意事项:
- 我需要使用
exec它的-a开关,它改变了进程的第零个参数。我希望有一个替代方法exec来做到这一点,但我不知道,现在这种行为让我很好奇。 - 当然,我需要一个子shell,因为我希望我的脚本继续。同样,任何替代方案都将受到欢迎。在子shell中甚至是
exec一件好事吗? time'ing 一个 subshell 通常工作正常,所以它确实与exec.
有人能指出我正确的方向吗?我不确定在任何参考资料中从哪里开始,exec描述非常简洁。
更新: 实际上,我只是“幸运”,因为time这里是内置的 bash。它根本不使用/usr/bin/time或使用任何其他进程进行解析:
$ env (exec -a foo echo hello)
bash: syntax error near unexpected token `exec'
实际上这是有道理的,我们不能将 subshell 作为参数传递。知道如何以其他方式做到这一点吗?
更新: 总而言之,我们在这里有四个很好的答案,都是不同的,并且可能缺少一些东西:
使用 bash 默认和
time正常使用的实际文件系统链接(硬链接或符号链接)。归功于 hek2mgl。ln $(which echo) foo && time ./foo hello && rm foofork用于time使用 bash 和exec使用没有特殊语法的 bash 子shell。time bash -c 'exec -a foo echo hello'fork使用timebash 但exec使用了一个小包装器。time launch -a foo echo hellofork以及exec使用time具有特殊语法的 bash。归功于 sjnarv。time { (exec -a foo echo hello); }
我认为解决方案 1 的影响较小,time因为计时器不必exec在“代理”程序中计算,但不是很实用(许多文件系统链接),在技术上也不理想。在所有其他情况下,我们实际上是exec两次:一次加载代理程序(2 和 4 的子shell,3 的包装器),一次加载实际程序。这意味着time将计算第二个exec。虽然它可能非常便宜,exec但实际上文件系统查找可能非常慢(特别是如果它通过 搜索PATH,无论是本身exec*p还是代理进程)。
因此,唯一干净的方法(就该问题的答案而言)是修补 bash 以修改其time关键字,以便它可以exec同时将第零个参数设置为非零值。它可能看起来像time -a foo echo hello。