在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
$
答案 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函数。