在 中eval <command>
,如何eval
评估以下命令?
是否
eval
创建一个 shell 子进程来评估<command>
?如果不是,是否
eval
依赖当前的shell进程来评估它?
注意
eval
是一个内置进程,因此没有为eval
自己创建子进程。<command>
在执行之前,可能会或可能不会创建一个子进程来运行它,具体取决于是否<command>
是内置进程。
用于评估上述命令的 shell 子进程不是注释中提到的两个中的任何一个。
谢谢。
答案1
有效的做法eval
是解析参数、扩展变量等,然后正常执行生成的字符串。
因此,例如:
$ i=ls
$ eval $i
这里eval
将替换$i
为ls
and然后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。