Выполняется ли eval путем создания процесса оболочки для оценки следующей команды?

В eval <command> , как eval оценивает следующую команду?

  • eval создает подпроцесс оболочки для оценки <command> ?

  • Если нет, полагается ли eval на текущий процесс оболочки для его оценки?

Обратите внимание, что

  • eval является встроенным, поэтому нет никакого подпроцесса, созданного для самого eval .
  • Перед выполнением <command> может быть или не быть подпроцессом, созданным для его запуска, в зависимости от того, является ли <command> не встроенным.

Подпроцесс оболочки для оценки упомянутой выше команды не является ни одним из двух, упомянутых в примечании.

Благодарю.

Эффективное выполнение eval – это анализ аргументов, расширение переменных и т. Д., А затем результирующая строка выполняется как обычно.

Так, например:

 $ i=ls $ eval $i 

Здесь eval заменяет $i на ls а затем запускает команду ls как обычно (так что fork() / exec() запускает ls процесс).

Если, однако, вы сделали

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

то новый процесс не создается, потому что echo hello запускается как встроенный.

Мы видим, что никакая оболочка не создается путем установки переменных:

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

$a может быть установлено только 100, если это было сделано в текущей оболочке.

Таким образом, сам eval самом деле является просто парсером и выполняется в текущей оболочке; результаты этой строки могут или не могут создать новый процесс, как и любая другая команда.

Я не знаю о нижнем, но на практике он работает так же, как source somefile , где он просто запускает эти команды в текущем процессе оболочки, не создавая новый процесс.

А также я бы использовал слово «строка», а не «команды», так как это то, что он делает. Это работает, но не имеет команды:

 $ 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 

Eval не создает новый процесс только для цели eval .

Eval скорее повторяет парсер с конкатенацией eval -arguments.

Результат этого разбора затем запускается в той же оболочке. Однако, если аргументы требуют создать под-оболочку для команды, это делается.

Поэтому основной целью eval является повторное использование анализатора.