Unix & Linux: What's the difference between eval and exec? (5 Solutions!!)
Channel: Roel Van de Paar
Date: 2020-08-11

Unix & Linux: What's the difference between eval and exec?


The Question: eval and exec are both built in commands of bash(1) that execute commands.
I also see exec has a few options but is that the only difference? What happens
to their context?

Solutions: Please watch the whole video to see all solutions, in order of how many people found them helpful

== This solution helped 27 people ==
exec does not create a new process. It replaces the current process with the
new command. If you did this on the command line then it will effectively end
your shell session (and maybe log you out or close the terminal window!)
e.g.
ksh% bash
bash-4.2$ exec /bin/echo hello
hello
ksh%
Here I'm in ksh (my normal shell). I start bash and then inside bash I exec /
bin/echo. We can see that I've been dropped back into ksh afterwards because
the bash process was replace by /bin/echo.

== This solution helped 141 people ==
eval and exec are completely different beasts. (Apart from the fact that both
will run commands, but so does everything you do in a shell.)
$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
Replace the shell with the given command.
What exec cmd does, is exactly the same as just running cmd, except that the
current shell is replaced with the command, instead of a separate process being
run. Internally, running say /bin/ls will call fork() to create a child
process, and then exec() in the child to execute /bin/ls. exec /bin/ls on the
other hand will not fork, but just replaces the shell.
Compare:
$ bash -c 'echo $$ ; ls -l /proc/self ; echo foo'
7218
lrwxrwxrwx 1 root root 0 Jun 30 16:49 /proc/self -＞ 7219
foo
with
$ bash -c 'echo $$ ; exec ls -l /proc/self ; echo foo'
7217
lrwxrwxrwx 1 root root 0 Jun 30 16:49 /proc/self -＞ 7217
echo $$ prints the PID of the shell I started, and listing /proc/self gives us
the PID of the ls that was ran from the shell. Usually, the process IDs are
different, but with exec the shell and ls have the same process ID. Also, the
command following exec didn't run, since the shell was replaced.
----
On the other hand:
$ help eval
eval: eval [arg ...]
Execute arguments as a shell command.
eval will run the arguments as a command in the current shell. In other words
eval foo bar is the same as just foo bar. But variables will be expanded before
executing, so we can execute commands saved in shell variables:
$ unset bar
$ cmd="bar=foo"
$ eval "$cmd"
$ echo "$bar"
foo
It will not create a child process, so the variable is set in the current
shell. (Of course eval /bin/ls will create a child process, the same way a
plain old /bin/ls would.)
Or we could have a command that outputs shell commands. Running ssh-agent
starts the agent in the background, and outputs a bunch of variable
assignments, which could be set in the current shell and used by child
processes (the ssh commands you would run). Hence ssh-agent can be started
with:
eval $(ssh-agent)
And the current shell will get the variables for other commands to inherit.
----
Of course, if the variable cmd happened to contain something like rm -rf $HOME,
then running eval "$cmd" would not be something you'd want to do. Even things
like command substitutions inside the string would be processed, so one should
really be sure that the input to eval is safe before using it.
Often, it's possible to avoid eval and avoid even accidentally mixing code and
data in the wrong way.

With thanks & praise to God, and with thanks to the many people who have made this project possible! | Content (except music & images) licensed under cc by-sa 3.0 | Music: https://www.bensound.com/royalty-free-music | Images: https://stocksnap.io/license & others | With thanks to user Willian Paixao (https://unix.stackexchange.com/users/21240), user user180452 (https://unix.stackexchange.com/users/180452), user Stephen Harris (https://unix.stackexchange.com/users/168757), user Sergiy Kolodyazhnyy (https://unix.stackexchange.com/users/85039), user Mateen Ulhaq (https://unix.stackexchange.com/users/162369), user ilkkachu (https://unix.stackexchange.com/users/170373), and the Stack Exchange Network (http://unix.stackexchange.com/questions/296838). Trademarks are property of their respective owners. Disclaimer: All information is provided "AS IS" without warranty of any kind. You are responsible for your own actions. Please contact me if anything is amiss at Roel D.OT VandePaar A.T gmail.com.