Bash / usr / bin / time命令在子shell中运行命令

时间:2014-10-31 16:22:27

标签: bash time

在bash脚本(在REHL5上运行)中,我使用/ usr / bin / time命令(不是内置时间命令)来记录我在同一个脚本中运行的其他命令的运行时间。我面临的问题是,我想要记录的一些命令不是内置命令或外部脚本,而是在脚本中声明或来自不同脚本的函数。我发现time命令失败了,如下所示:

/usr/bin/time: cannot run shared-func: No such file or directory

这意味着我在其他地方声明的函数shared-func()在作用域中不可见,因此时间不能运行该命令。我已经运行了一些测试,并且已经验证了这个错误背后的原因实际上是因为time命令试图在新的子shell中执行它的命令,因此丢失了其范围内的每个声明的函数或变量。有办法解决这个问题吗?理想的解决方案是强制time命令改变其行为并使用当前shell执行其命令,但如果不可能,我也对任何其他解决方案感兴趣。

为了记录,下面是我跑的测试。我创建了两个小脚本:

shared.sh:

function shared-func() {
    echo "The shared function is visible."
}

test.sh:

#!/bin/bash

function record-timestamp() {
    /usr/bin/time -f % -a -o timestamps.csv "$@"
}

source "shared.sh"
record-timestamp shared-func

这是测试:

$ ./test.sh
/usr/bin/time: cannot run shared-func: No such file or directory
$ 

1 个答案:

答案 0 :(得分:0)

一个不同的进程,是的。一个子shell ,没有。

子shell是您的父shell分叉但不exec()时获得的子代码 - 它是通过复制当前shell实例而创建的新进程。函数可以在子shell中访问,但它们不会对父shell产生直接影响(当它退出时,处理状态的变化会与子shell一起消失)。

当你在不使用exec的情况下启动外部程序时,shell首先分叉,然后调用execve()来调用新程序。 execve()用正在运行的程序替换内存中的进程映像 - 所以它不是fork(),即创建子shell导致失败;相反,它是exec(),是一个单独程序的调用。

即使你的新进程也是一个shell,如果它经历了任何exec() - 系列调用它不是一个子shell--它是一个全新的过程。


tl; dr :您无法使用外部程序将shell函数调用包装在当前shell中,因为外部程序的调用始终使用execve()execve()始终清除进程状态 - 包括未导出的shell函数。