eval是通过创建一个shell进程来评估以下命令来实现的吗?

eval是通过创建一个shell进程来评估以下命令来实现的吗?

在 中eval <command>,如何eval评估以下命令?

  • 是否eval创建一个 shell 子进程来评估<command>

  • 如果不是,是否eval依赖当前的shell进程来评估它?

注意

  • eval是一个内置进程,因此没有为eval自己创建子进程。
  • <command>在执行之前,可能会或可能不会创建一个子进程来运行它,具体取决于是否<command>是内置进程。

用于评估上述命令的 shell 子进程不是注释中提到的两个中的任何一个。

谢谢。

答案1

有效的做法eval是解析参数、扩展变量等,然后正常执行生成的字符串。

因此,例如:

$ i=ls
$ eval $i

这里eval将替换$ilsand然后ls正常运行命令(因此它将fork()/exec()运行该ls进程)。

然而如果你这么做了

$ i="echo hello"
$ eval $i
hello

那么不会创建新进程,因为它echo hello是作为内置进程运行的。

通过设置变量我们可以看到没有创建shell:

$ a=0
$ i="a=100"
$ eval $i
$ echo $a
100

$a如果在当前 shell 中完成,则只能设置为 100。

所以它eval本身实际上只是一个解析器,并且是在当前 shell 中完成的;这结果该字符串可能会也可能不会创建新进程,与任何其他命令相同。

答案2

我不知道下面的情况,但实际上,它的运行方式就像source somefile,它只是在当前的 shell 进程中运行这些命令,而不生成新进程。

而且我会使用“字符串”这个词而不是“命令”,因为这就是它的作用。这有效,但没有命令:

$ eval ""

或者这在技术上不是一个命令:

$ eval "x(){ echo test;}"
$ x
test

并表明它并不总是制定新流程(所以我不同意威廉的观点):

在一个终端中:

$ echo $$
9983
$ eval "sleep 100"  

在另一个:

$ ps -ef --forest
peter     9983  2840  0 14:21 pts/41   00:00:00  \_ /bin/bash
peter    17339  9983  0 14:26 pts/41   00:00:00  |   \_ sleep 100

但如果你这样做,它会出于某种原因:

$ eval 'sleep 100' &
[1] 20675

$ ps --forest
  PID TTY          TIME CMD
 9983 pts/41   00:00:00 bash
20675 pts/41   00:00:00  \_ bash
20676 pts/41   00:00:00  |   \_ sleep
20757 pts/41   00:00:00  \_ ps

答案3

Eval 不会仅仅为了 的目的而创建新进程eval

Eval 而是使用 - 参数的串联来重新运行解析器eval

然后,解析的结果将在同一 shell 中运行。但是,如果参数需要为命令创建子 shell,则完成此操作。

所以eval的主要目的是重新运行解析器。

答案4

试试这个:在 eval 期间扩展$$Between ,在 eval 之前扩展:''$$""

$ eval /bin/echo '$$' "$$"
17899 17899

因此,由于两者在同一进程中扩展,因此不存在由 eval 启动的子 shell。请注意,我采用了非 shell 函数 echo。

相关内容