exec
используется для замены текущего процесса оболочки новым и обработки перенаправления потока/дескрипторов файлов, если команда не указана. eval
используется для оценки строк как команд. Оба могут использоваться для создания и выполнения команды с аргументами, известными во время выполнения, но exec
заменяет процесс текущей оболочки в дополнение к выполнению команд.
Синтаксис:
exec [-cl] [-a name] [command [arguments]]
Согласно мануалу, если указана команда, эта встроенная
...заменяет оболочку. Новый процесс не создается. Аргументы становятся аргументами команды.
Другими словами, если вы запускали bash
с PID 1234 и запускали exec top -u root
в этой оболочке, top
команда будет иметь PID 1234 и заменит ваш процесс оболочки.
Где это полезно? В чем-то, известном как сценарии-оболочки. Такие сценарии создают наборы аргументов или принимают определенные решения о том, какие переменные передавать в среду, а затем используют exec
для замены себя любой указанной командой и, конечно же, предоставляют те же аргументы, что и сценарий-оболочка. построенный по пути.
В руководстве также говорится следующее:
Если команда не указана, любые перенаправления вступают в силу в текущей оболочке.
Это позволяет нам перенаправлять что-либо из выходных потоков текущей оболочки в файл. Это может быть полезно для регистрации или фильтрации, когда вы не хотите видеть stdout
команд, а только stderr
. Например, вот так:
bash-4.3$ exec 3>&1
bash-4.3$ exec > test_redirect.txt
bash-4.3$ date
bash-4.3$ echo "HELLO WORLD"
bash-4.3$ exec >&3
bash-4.3$ cat test_redirect.txt
2017年 05月 20日 星期六 05:01:51 MDT
HELLO WORLD
Это поведение делает его удобным для регистрации в сценариях оболочки, перенаправления потоков в отдельные файлы или процессы и других забавных вещей. с файловыми дескрипторами.
На уровне исходного кода по крайней мере для bash
версии 4.3 встроенный exec
определен в builtins/exec.def
. Он анализирует полученные команды и, если они есть, передает их функции shell_execve()
, определенной в файле execute_cmd.c
.
Короче говоря, существует семейство команд exec
в языке программирования C, и shell_execve()
по сути представляет собой функцию-оболочку для execve
:
/* Call execve (), handling interpreting shell scripts, and handling
exec failures. */
int
shell_execve (command, args, env)
char *command;
char **args, **env;
{
В руководстве по bash 4.3 указано (выделение добавлено мной):
Аргументы считываются и объединяются в одну команду. Затем эта команда считывается и выполняется оболочкой, и ее статус выхода возвращается как значение eval.
Обратите внимание, что замены процесса не происходит.В отличие от exec
, где целью является имитация функциональности execve()
, встроенный eval
служит только для «оценки» аргументов, как если бы пользователь набрал их в командной строке. Таким образом, создаются новые процессы.
Где это может быть полезно? Как указал Жиль в этом ответе , «... eval используется не очень часто. В некоторых оболочках наиболее распространенным использованием является получение значения переменной, имя которой неизвестно до времени выполнения». Лично я использовал его в паре скриптов на Ubuntu, где было необходимо выполнить/оценить команду на основе конкретной рабочей области, которую в данный момент использовал пользователь.
На уровне исходного кода он определен в builtins/eval.def
и передает проанализированную входную строку в функцию evalstring()
.
Помимо прочего, eval
может назначать переменные, которые остаются в текущей среде выполнения оболочки, в то время как exec
не может:
$ eval x=42
$ echo $x
42
$ exec x=42
bash: exec: x=42: not found